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
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 KeySpec * g_keys;
80 static ZoneSpec * g_zones;
81 static ZoneSpec g_zoneSpec;
82 static const char * g_filename;
83
84 #define YYPARSE_PARAM context
85
86 void
87 SetupOptions
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
135 commands:
136 |
137 commands command SEMICOLON
138 ;
139
140
141 command:
142 options_set
143 |
144 zone_set
145 |
146 key_set
147 ;
148
149
150 options_set:
151 OPTIONS optionscontent
152 {
153 // SetupOptions( &g_optionsInfo, context );
154 }
155 ;
156
157 optionscontent:
158 OBRACE optionsstatements EBRACE
159 ;
160
161 optionsstatements:
162 |
163 optionsstatements optionsstatement SEMICOLON
164 ;
165
166
167 optionsstatement:
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
197 key_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
218 zone_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
264 zonecontent:
265 OBRACE zonestatements EBRACE
266
267 zonestatements:
268 |
269 zonestatements zonestatement SEMICOLON
270 ;
271
272 zonestatement:
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
296 addresscontent:
297 OBRACE addressstatements EBRACE
298 {
299 }
300
301 addressstatements:
302 |
303 addressstatements addressstatement SEMICOLON
304 {
305 }
306 ;
307
308 addressstatement:
309 DOTTED_DECIMAL_ADDRESS
310 {
311 }
312 ;
313
314
315 keycontent:
316 OBRACE keystatements EBRACE
317 {
318 }
319
320 keystatements:
321 |
322 keystatements keystatement SEMICOLON
323 {
324 }
325 ;
326
327 keystatement:
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
348 networkaddress:
349 DOTTED_DECIMAL_ADDRESS
350 |
351 HOSTNAME
352 |
353 WILDCARD
354 ;
355
356 block:
357 OBRACE zonestatements EBRACE SEMICOLON
358 ;
359
360 statements:
361 |
362 statements statement
363 ;
364
365 statement:
366 block
367 {
368 $<string>$ = NULL;
369 }
370 |
371 QUOTEDSTRING
372 {
373 $<string>$ = $1;
374 }
375 %%
376
377 int yywrap(void);
378
379 extern int yylineno;
380
yyerror(const char * str)381 void yyerror( const char *str )
382 {
383 fprintf( stderr,"%s:%d: error: %s\n", g_filename, yylineno, str );
384 }
385
yywrap()386 int yywrap()
387 {
388 return 1;
389 }
390
391
392 int
ParseConfig(DaemonInfo * d,const char * file)393 ParseConfig
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
541 exit:
542
543 return err;
544 }
545
546
547 void
SetupOptions(OptionsInfo * info,void * context)548 SetupOptions
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