You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
586 lines
10 KiB
586 lines
10 KiB
/* -*- Mode: C; tab-width: 4 -*-
|
|
*
|
|
* Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
%{
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "mDNSEmbeddedAPI.h"
|
|
#include "DebugServices.h"
|
|
#include "dnsextd.h"
|
|
|
|
void yyerror( const char* error );
|
|
int yylex(void);
|
|
|
|
|
|
typedef struct StringListElem
|
|
{
|
|
char * string;
|
|
struct StringListElem * next;
|
|
} StringListElem;
|
|
|
|
|
|
typedef struct OptionsInfo
|
|
{
|
|
char server_address[ 256 ];
|
|
int server_port;
|
|
char source_address[ 256 ];
|
|
int source_port;
|
|
int private_port;
|
|
int llq_port;
|
|
} OptionsInfo;
|
|
|
|
|
|
typedef struct ZoneInfo
|
|
{
|
|
char name[ 256 ];
|
|
char certificate_name[ 256 ];
|
|
char allow_clients_file[ 256 ];
|
|
char allow_clients[ 256 ];
|
|
char key[ 256 ];
|
|
} ZoneInfo;
|
|
|
|
|
|
typedef struct KeySpec
|
|
{
|
|
char name[ 256 ];
|
|
char algorithm[ 256 ];
|
|
char secret[ 256 ];
|
|
struct KeySpec * next;
|
|
} KeySpec;
|
|
|
|
|
|
typedef struct ZoneSpec
|
|
{
|
|
char name[ 256 ];
|
|
DNSZoneSpecType type;
|
|
StringListElem * allowUpdate;
|
|
StringListElem * allowQuery;
|
|
char key[ 256 ];
|
|
struct ZoneSpec * next;
|
|
} ZoneSpec;
|
|
|
|
|
|
static StringListElem * g_stringList = NULL;
|
|
static KeySpec * g_keys;
|
|
static ZoneSpec * g_zones;
|
|
static ZoneSpec g_zoneSpec;
|
|
static const char * g_filename;
|
|
|
|
#define YYPARSE_PARAM context
|
|
|
|
void
|
|
SetupOptions
|
|
(
|
|
OptionsInfo * info,
|
|
void * context
|
|
);
|
|
|
|
%}
|
|
|
|
%union
|
|
{
|
|
int number;
|
|
char * string;
|
|
}
|
|
|
|
%token OPTIONS
|
|
%token LISTEN_ON
|
|
%token NAMESERVER
|
|
%token PORT
|
|
%token ADDRESS
|
|
%token LLQ
|
|
%token PUBLIC
|
|
%token PRIVATE
|
|
%token ALLOWUPDATE
|
|
%token ALLOWQUERY
|
|
%token KEY
|
|
%token ALGORITHM
|
|
%token SECRET
|
|
%token ISSUER
|
|
%token SERIAL
|
|
%token ZONE
|
|
%token TYPE
|
|
%token ALLOW
|
|
%token OBRACE
|
|
%token EBRACE
|
|
%token SEMICOLON
|
|
%token IN
|
|
%token <string> DOTTED_DECIMAL_ADDRESS
|
|
%token <string> WILDCARD
|
|
%token <string> DOMAINNAME
|
|
%token <string> HOSTNAME
|
|
%token <string> QUOTEDSTRING
|
|
%token <number> NUMBER
|
|
|
|
%type <string> addressstatement
|
|
%type <string> networkaddress
|
|
|
|
%%
|
|
|
|
commands:
|
|
|
|
|
commands command SEMICOLON
|
|
;
|
|
|
|
|
|
command:
|
|
options_set
|
|
|
|
|
zone_set
|
|
|
|
|
key_set
|
|
;
|
|
|
|
|
|
options_set:
|
|
OPTIONS optionscontent
|
|
{
|
|
// SetupOptions( &g_optionsInfo, context );
|
|
}
|
|
;
|
|
|
|
optionscontent:
|
|
OBRACE optionsstatements EBRACE
|
|
;
|
|
|
|
optionsstatements:
|
|
|
|
|
optionsstatements optionsstatement SEMICOLON
|
|
;
|
|
|
|
|
|
optionsstatement:
|
|
statements
|
|
|
|
|
LISTEN_ON addresscontent
|
|
{
|
|
}
|
|
|
|
|
LISTEN_ON PORT NUMBER addresscontent
|
|
{
|
|
}
|
|
|
|
|
NAMESERVER ADDRESS networkaddress
|
|
{
|
|
}
|
|
|
|
|
NAMESERVER ADDRESS networkaddress PORT NUMBER
|
|
{
|
|
}
|
|
|
|
|
PRIVATE PORT NUMBER
|
|
{
|
|
( ( DaemonInfo* ) context )->private_port = mDNSOpaque16fromIntVal( $3 );
|
|
}
|
|
|
|
|
LLQ PORT NUMBER
|
|
{
|
|
( ( DaemonInfo* ) context )->llq_port = mDNSOpaque16fromIntVal( $3 );
|
|
}
|
|
;
|
|
|
|
key_set:
|
|
KEY QUOTEDSTRING OBRACE SECRET QUOTEDSTRING SEMICOLON EBRACE
|
|
{
|
|
KeySpec * keySpec;
|
|
|
|
keySpec = ( KeySpec* ) malloc( sizeof( KeySpec ) );
|
|
|
|
if ( !keySpec )
|
|
{
|
|
LogMsg("ERROR: memory allocation failure");
|
|
YYABORT;
|
|
}
|
|
|
|
strncpy( keySpec->name, $2, sizeof( keySpec->name ) );
|
|
strncpy( keySpec->secret, $5, sizeof( keySpec->secret ) );
|
|
|
|
keySpec->next = g_keys;
|
|
g_keys = keySpec;
|
|
}
|
|
;
|
|
|
|
zone_set:
|
|
ZONE QUOTEDSTRING zonecontent
|
|
{
|
|
ZoneSpec * zoneSpec;
|
|
|
|
zoneSpec = ( ZoneSpec* ) malloc( sizeof( ZoneSpec ) );
|
|
|
|
if ( !zoneSpec )
|
|
{
|
|
LogMsg("ERROR: memory allocation failure");
|
|
YYABORT;
|
|
}
|
|
|
|
strncpy( zoneSpec->name, $2, sizeof( zoneSpec->name ) );
|
|
zoneSpec->type = g_zoneSpec.type;
|
|
strcpy( zoneSpec->key, g_zoneSpec.key );
|
|
zoneSpec->allowUpdate = g_zoneSpec.allowUpdate;
|
|
zoneSpec->allowQuery = g_zoneSpec.allowQuery;
|
|
|
|
zoneSpec->next = g_zones;
|
|
g_zones = zoneSpec;
|
|
}
|
|
|
|
|
ZONE QUOTEDSTRING IN zonecontent
|
|
{
|
|
ZoneSpec * zoneSpec;
|
|
|
|
zoneSpec = ( ZoneSpec* ) malloc( sizeof( ZoneSpec ) );
|
|
|
|
if ( !zoneSpec )
|
|
{
|
|
LogMsg("ERROR: memory allocation failure");
|
|
YYABORT;
|
|
}
|
|
|
|
strncpy( zoneSpec->name, $2, sizeof( zoneSpec->name ) );
|
|
zoneSpec->type = g_zoneSpec.type;
|
|
strcpy( zoneSpec->key, g_zoneSpec.key );
|
|
zoneSpec->allowUpdate = g_zoneSpec.allowUpdate;
|
|
zoneSpec->allowQuery = g_zoneSpec.allowQuery;
|
|
|
|
zoneSpec->next = g_zones;
|
|
g_zones = zoneSpec;
|
|
}
|
|
;
|
|
|
|
zonecontent:
|
|
OBRACE zonestatements EBRACE
|
|
|
|
zonestatements:
|
|
|
|
|
zonestatements zonestatement SEMICOLON
|
|
;
|
|
|
|
zonestatement:
|
|
TYPE PUBLIC
|
|
{
|
|
g_zoneSpec.type = kDNSZonePublic;
|
|
}
|
|
|
|
|
TYPE PRIVATE
|
|
{
|
|
g_zoneSpec.type = kDNSZonePrivate;
|
|
}
|
|
|
|
|
ALLOWUPDATE keycontent
|
|
{
|
|
g_zoneSpec.allowUpdate = g_stringList;
|
|
g_stringList = NULL;
|
|
}
|
|
|
|
|
ALLOWQUERY keycontent
|
|
{
|
|
g_zoneSpec.allowQuery = g_stringList;
|
|
g_stringList = NULL;
|
|
}
|
|
;
|
|
|
|
addresscontent:
|
|
OBRACE addressstatements EBRACE
|
|
{
|
|
}
|
|
|
|
addressstatements:
|
|
|
|
|
addressstatements addressstatement SEMICOLON
|
|
{
|
|
}
|
|
;
|
|
|
|
addressstatement:
|
|
DOTTED_DECIMAL_ADDRESS
|
|
{
|
|
}
|
|
;
|
|
|
|
|
|
keycontent:
|
|
OBRACE keystatements EBRACE
|
|
{
|
|
}
|
|
|
|
keystatements:
|
|
|
|
|
keystatements keystatement SEMICOLON
|
|
{
|
|
}
|
|
;
|
|
|
|
keystatement:
|
|
KEY DOMAINNAME
|
|
{
|
|
StringListElem * elem;
|
|
|
|
elem = ( StringListElem* ) malloc( sizeof( StringListElem ) );
|
|
|
|
if ( !elem )
|
|
{
|
|
LogMsg("ERROR: memory allocation failure");
|
|
YYABORT;
|
|
}
|
|
|
|
elem->string = $2;
|
|
|
|
elem->next = g_stringList;
|
|
g_stringList = elem;
|
|
}
|
|
;
|
|
|
|
|
|
networkaddress:
|
|
DOTTED_DECIMAL_ADDRESS
|
|
|
|
|
HOSTNAME
|
|
|
|
|
WILDCARD
|
|
;
|
|
|
|
block:
|
|
OBRACE zonestatements EBRACE SEMICOLON
|
|
;
|
|
|
|
statements:
|
|
|
|
|
statements statement
|
|
;
|
|
|
|
statement:
|
|
block
|
|
{
|
|
$<string>$ = NULL;
|
|
}
|
|
|
|
|
QUOTEDSTRING
|
|
{
|
|
$<string>$ = $1;
|
|
}
|
|
%%
|
|
|
|
int yywrap(void);
|
|
|
|
extern int yylineno;
|
|
|
|
void yyerror( const char *str )
|
|
{
|
|
fprintf( stderr,"%s:%d: error: %s\n", g_filename, yylineno, str );
|
|
}
|
|
|
|
int yywrap()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
|
|
int
|
|
ParseConfig
|
|
(
|
|
DaemonInfo * d,
|
|
const char * file
|
|
)
|
|
{
|
|
extern FILE * yyin;
|
|
DNSZone * zone;
|
|
DomainAuthInfo * key;
|
|
KeySpec * keySpec;
|
|
ZoneSpec * zoneSpec;
|
|
int err = 0;
|
|
|
|
g_filename = file;
|
|
|
|
// Tear down the current zone specifiers
|
|
|
|
zone = d->zones;
|
|
|
|
while ( zone )
|
|
{
|
|
DNSZone * next = zone->next;
|
|
|
|
key = zone->updateKeys;
|
|
|
|
while ( key )
|
|
{
|
|
DomainAuthInfo * nextKey = key->next;
|
|
|
|
free( key );
|
|
|
|
key = nextKey;
|
|
}
|
|
|
|
key = zone->queryKeys;
|
|
|
|
while ( key )
|
|
{
|
|
DomainAuthInfo * nextKey = key->next;
|
|
|
|
free( key );
|
|
|
|
key = nextKey;
|
|
}
|
|
|
|
free( zone );
|
|
|
|
zone = next;
|
|
}
|
|
|
|
d->zones = NULL;
|
|
|
|
yyin = fopen( file, "r" );
|
|
require_action( yyin, exit, err = 0 );
|
|
|
|
err = yyparse( ( void* ) d );
|
|
require_action( !err, exit, err = 1 );
|
|
|
|
for ( zoneSpec = g_zones; zoneSpec; zoneSpec = zoneSpec->next )
|
|
{
|
|
StringListElem * elem;
|
|
mDNSu8 * ok;
|
|
|
|
zone = ( DNSZone* ) malloc( sizeof( DNSZone ) );
|
|
require_action( zone, exit, err = 1 );
|
|
memset( zone, 0, sizeof( DNSZone ) );
|
|
|
|
zone->next = d->zones;
|
|
d->zones = zone;
|
|
|
|
// Fill in the domainname
|
|
|
|
ok = MakeDomainNameFromDNSNameString( &zone->name, zoneSpec->name );
|
|
require_action( ok, exit, err = 1 );
|
|
|
|
// Fill in the type
|
|
|
|
zone->type = zoneSpec->type;
|
|
|
|
// Fill in the allow-update keys
|
|
|
|
for ( elem = zoneSpec->allowUpdate; elem; elem = elem->next )
|
|
{
|
|
mDNSBool found = mDNSfalse;
|
|
|
|
for ( keySpec = g_keys; keySpec; keySpec = keySpec->next )
|
|
{
|
|
if ( strcmp( elem->string, keySpec->name ) == 0 )
|
|
{
|
|
DomainAuthInfo * authInfo = malloc( sizeof( DomainAuthInfo ) );
|
|
mDNSs32 keylen;
|
|
require_action( authInfo, exit, err = 1 );
|
|
memset( authInfo, 0, sizeof( DomainAuthInfo ) );
|
|
|
|
ok = MakeDomainNameFromDNSNameString( &authInfo->keyname, keySpec->name );
|
|
if (!ok) { free(authInfo); err = 1; goto exit; }
|
|
|
|
keylen = DNSDigest_ConstructHMACKeyfromBase64( authInfo, keySpec->secret );
|
|
if (keylen < 0) { free(authInfo); err = 1; goto exit; }
|
|
|
|
authInfo->next = zone->updateKeys;
|
|
zone->updateKeys = authInfo;
|
|
|
|
found = mDNStrue;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Log this
|
|
require_action( found, exit, err = 1 );
|
|
}
|
|
|
|
// Fill in the allow-query keys
|
|
|
|
for ( elem = zoneSpec->allowQuery; elem; elem = elem->next )
|
|
{
|
|
mDNSBool found = mDNSfalse;
|
|
|
|
for ( keySpec = g_keys; keySpec; keySpec = keySpec->next )
|
|
{
|
|
if ( strcmp( elem->string, keySpec->name ) == 0 )
|
|
{
|
|
DomainAuthInfo * authInfo = malloc( sizeof( DomainAuthInfo ) );
|
|
mDNSs32 keylen;
|
|
require_action( authInfo, exit, err = 1 );
|
|
memset( authInfo, 0, sizeof( DomainAuthInfo ) );
|
|
|
|
ok = MakeDomainNameFromDNSNameString( &authInfo->keyname, keySpec->name );
|
|
if (!ok) { free(authInfo); err = 1; goto exit; }
|
|
|
|
keylen = DNSDigest_ConstructHMACKeyfromBase64( authInfo, keySpec->secret );
|
|
if (keylen < 0) { free(authInfo); err = 1; goto exit; }
|
|
|
|
authInfo->next = zone->queryKeys;
|
|
zone->queryKeys = authInfo;
|
|
|
|
found = mDNStrue;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Log this
|
|
require_action( found, exit, err = 1 );
|
|
}
|
|
}
|
|
|
|
exit:
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
void
|
|
SetupOptions
|
|
(
|
|
OptionsInfo * info,
|
|
void * context
|
|
)
|
|
{
|
|
DaemonInfo * d = ( DaemonInfo* ) context;
|
|
|
|
if ( strlen( info->source_address ) )
|
|
{
|
|
inet_pton( AF_INET, info->source_address, &d->addr.sin_addr );
|
|
}
|
|
|
|
if ( info->source_port )
|
|
{
|
|
d->addr.sin_port = htons( ( mDNSu16 ) info->source_port );
|
|
}
|
|
|
|
if ( strlen( info->server_address ) )
|
|
{
|
|
inet_pton( AF_INET, info->server_address, &d->ns_addr.sin_addr );
|
|
}
|
|
|
|
if ( info->server_port )
|
|
{
|
|
d->ns_addr.sin_port = htons( ( mDNSu16 ) info->server_port );
|
|
}
|
|
|
|
if ( info->private_port )
|
|
{
|
|
d->private_port = mDNSOpaque16fromIntVal( info->private_port );
|
|
}
|
|
|
|
if ( info->llq_port )
|
|
{
|
|
d->llq_port = mDNSOpaque16fromIntVal( info->llq_port );
|
|
}
|
|
}
|