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