Commit 028b1f6a authored by Ted Lemon's avatar Ted Lemon
Browse files

Redo key declarations to match BIND. Add base64 parsing.

parent 96e16c0e
......@@ -43,7 +43,7 @@
#ifndef lint
static char copyright[] =
"$Id: parse.c,v 1.69 2000/04/04 06:27:35 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
"$Id: parse.c,v 1.70 2000/04/06 22:46:26 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
......@@ -1125,6 +1125,93 @@ int parse_option_code_definition (cfile, option)
return 1;
}
/*
* base64 :== NUMBER_OR_STRING
*/
int parse_base64 (data, cfile)
struct data_string *data;
struct parse *cfile;
{
enum dhcp_token token;
const char *val;
int i, j;
unsigned acc = 0;
static char from64 [] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */
64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */
52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */
60, 61, 64, 64, 64, 64, 64, 64, /* 90:;<=>? */
64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */
7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */
15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */
23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */
64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */
33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */
41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */
59, 50, 51, 64, 64, 64, 64, 64};/* xyz{|}~ */
token = next_token (&val, cfile);
if (token == STRING) {
data -> len = strlen (val) + 1;
if (!buffer_allocate (&data -> buffer, data -> len, MDL)) {
parse_warn (cfile, "can't allocate string buffer");
return 0;
}
strcpy (data -> buffer -> data, val);
data -> terminated = 1;
data -> data = data -> buffer -> data;
return 1;
}
data -> len = strlen (val);
data -> len = (data -> len * 3) / 4;
if (!buffer_allocate (&data -> buffer, data -> len, MDL)) {
parse_warn (cfile, "can't allocate buffer for base64 data.");
data -> len = 0;
data -> data = (unsigned char *)0;
return 0;
}
j = 0;
for (i = 0; val [i] != '=' && val [i]; i++) {
unsigned foo = val [i];
if (foo < ' ' || foo > 'z') {
bad64:
parse_warn (cfile,
"invalid base64 character %d.", val [i]);
data_string_forget (data, MDL);
return 0;
}
foo = from64 [foo - ' '];
if (foo == 64)
goto bad64;
acc = (acc << 6) + foo;
switch (i % 4) {
case 0:
break;
case 1:
data -> buffer -> data [j++] = (acc >> 4);
acc = acc & 0x0f;
break;
case 2:
data -> buffer -> data [j++] = (acc >> 2);
acc = acc & 0x03;
break;
case 3:
data -> buffer -> data [j++] = acc;
acc = 0;
break;
}
}
if (i % 4)
parse_warn (cfile, "partial base64 value left over: %d.", acc);
data -> len = j;
data -> data = data -> buffer -> data;
return 1;
}
/*
* colon-seperated-hex-list :== NUMBER |
* NUMBER COLON colon-seperated-hex-list
......@@ -1238,7 +1325,6 @@ int parse_executable_statement (result, cfile, lose, case_context)
int known;
int flag;
struct dns_zone *zone;
struct tsig_key *tkey;
isc_result_t status;
token = peek_token (&val, cfile);
......@@ -1563,6 +1649,7 @@ int parse_executable_statement (result, cfile, lose, case_context)
parsers. */
case ZONE:
token = next_token (&val, cfile);
zone = (struct dns_zone *)0;
if (!dns_zone_allocate (&zone, MDL))
log_fatal ("no memory for new zone.");
zone -> name = parse_host_name (cfile);
......@@ -1573,26 +1660,13 @@ int parse_executable_statement (result, cfile, lose, case_context)
dns_zone_dereference (&zone, MDL);
return 0;
}
token = next_token (&val, cfile);
if (token != LBRACE) {
parse_warn (cfile, "expecting left brace");
goto badzone;
}
if (!parse_zone (zone, cfile))
goto badzone;
token = next_token (&val, cfile);
if (token != RBRACE) {
parse_warn (cfile, "expecting right brace.");
goto badzone;
}
status = enter_dns_zone (zone);
if (status == ISC_R_NOMEMORY)
log_fatal ("no memory to hash dns zone %s",
zone -> name);
if (status != ISC_R_SUCCESS) {
if (parse_semi (cfile))
parse_warn (cfile, "tsig key %s: %s",
tkey -> name,
parse_warn (cfile, "dns zone key %s: %s",
zone -> name,
isc_result_totext (status));
dns_zone_dereference (&zone, MDL);
return 0;
......@@ -1600,44 +1674,13 @@ int parse_executable_statement (result, cfile, lose, case_context)
return 1;
/* Also not really a statement, but same idea as above. */
case TSIG_KEY:
case KEY:
token = next_token (&val, cfile);
token = next_token (&val, cfile);
if (token != STRING) {
parse_warn (cfile, "expecting key name string.");
if (!parse_key (cfile)) {
*lose = 1;
skip_to_semi (cfile);
return 0;
}
if (!tsig_key_allocate (&tkey, MDL))
log_fatal ("no memory for tsig key");
tkey -> name = dmalloc (strlen (val) + 1, MDL);
if (!tkey -> name)
log_fatal ("no memory for tsig key name.");
strcpy (tkey -> name, val);
tkey -> algorithm = parse_host_name (cfile);
if (!tkey -> algorithm) {
parse_warn (cfile, "expecting key algorithim name.");
badtkey:
skip_to_semi (cfile);
tsig_key_dereference (&tkey, MDL);
return 0;
}
if (!parse_cshl (&tkey -> key, cfile))
goto badtkey;
status = enter_tsig_key (tkey);
if (status == ISC_R_NOMEMORY)
log_fatal ("no memory to hash tsig key %s",
tkey -> name);
if (status != ISC_R_SUCCESS) {
if (parse_semi (cfile))
parse_warn (cfile, "tsig key %s: %s",
tkey -> name,
isc_result_totext (status));
tsig_key_dereference (&tkey, MDL);
return 0;
}
return parse_semi (cfile);
return 1;
default:
if (config_universe && is_identifier (token)) {
......@@ -1663,9 +1706,11 @@ int parse_executable_statement (result, cfile, lose, case_context)
zone-statement :==
PRIMARY ip-addresses SEMI |
SECONDARY ip-addresses SEMI |
TSIG_KEY STRING SEMI
ip-addresses = ip-addr-or-hostname |
ip-addr-or-hostname COMMA ip-addresses */
key-reference SEMI
ip-addresses :== ip-addr-or-hostname |
ip-addr-or-hostname COMMA ip-addresses
key-reference :== KEY STRING |
KEY identifier */
int parse_zone (struct dns_zone *zone, struct parse *cfile)
{
......@@ -1674,6 +1719,12 @@ int parse_zone (struct dns_zone *zone, struct parse *cfile)
struct option_cache *oc;
int done = 0;
token = next_token (&val, cfile);
if (token != LBRACE) {
parse_warn (cfile, "expecting left brace");
return 0;
}
do {
token = peek_token (&val, cfile);
switch (token) {
......@@ -1735,10 +1786,10 @@ int parse_zone (struct dns_zone *zone, struct parse *cfile)
}
break;
case TSIG_KEY:
case KEY:
token = next_token (&val, cfile);
token = next_token (&val, cfile);
if (token != STRING) {
if (token != STRING && !is_identifier (token)) {
parse_warn (cfile, "expecting key name.");
skip_to_semi (cfile);
return 0;
......@@ -1755,9 +1806,105 @@ int parse_zone (struct dns_zone *zone, struct parse *cfile)
}
} while (!done);
token = next_token (&val, cfile);
if (token != RBRACE) {
parse_warn (cfile, "expecting right brace.");
return 0;
}
return 1;
}
/* key-statements :== key-statement |
key-statement key-statements
key-statement :==
ALGORITHM host-name SEMI |
secret-definition SEMI
secret-definition :== SECRET base64val |
SECRET STRING */
int parse_key (struct parse *cfile)
{
int token;
const char *val;
int done = 0;
struct tsig_key *key;
isc_result_t status;
token = next_token (&val, cfile);
if (token != STRING && !is_identifier (token)) {
parse_warn (cfile, "expecting key name string.");
skip_to_semi (cfile);
return 0;
}
key = (struct tsig_key *)0;
if (!tsig_key_allocate (&key, MDL))
log_fatal ("no memory for tsig key");
key -> name = dmalloc (strlen (val) + 1, MDL);
if (!key -> name)
log_fatal ("no memory for tsig key name.");
strcpy (key -> name, val);
token = next_token (&val, cfile);
if (token != LBRACE) {
parse_warn (cfile, "expecting left brace");
return 0;
}
do {
token = next_token (&val, cfile);
switch (token) {
case ALGORITHM:
if (key -> algorithm) {
parse_warn (cfile,
"key %s: too many algorithms",
key -> name);
goto rbad;
}
key -> algorithm = parse_host_name (cfile);
if (!key -> algorithm) {
parse_warn (cfile,
"expecting key algorithm name.");
goto rbad;
}
if (!parse_semi (cfile))
goto rbad;
break;
case SECRET:
if (key -> key.buffer) {
parse_warn (cfile, "key %s: too many secrets",
key -> name);
goto rbad;
}
if (!parse_base64 (&key -> key, cfile))
goto rbad;
if (!parse_semi (cfile))
goto rbad;
break;
default:
done = 1;
break;
}
} while (!done);
if (token != RBRACE) {
parse_warn (cfile, "expecting right brace.");
goto rbad;
}
status = enter_tsig_key (key);
if (status != ISC_R_SUCCESS) {
parse_warn (cfile, "tsig key %s: %s",
key -> name, isc_result_totext (status));
goto bad;
}
return 1;
rbad:
skip_to_rbrace (cfile, 1);
bad:
tsig_key_dereference (&key, MDL);
return 0;
}
/*
* on-statement :== event-types LBRACE executable-statements RBRACE
* event-types :== event-type OR event-types |
......@@ -3684,57 +3831,6 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
return 1;
}
int parse_auth_key (key_id, cfile)
struct data_string *key_id;
struct parse *cfile;
{
struct data_string key_data;
const char *val;
enum dhcp_token token;
const struct auth_key *key, *old_key = (struct auth_key *)0;
struct auth_key *new_key;
memset (&key_data, 0, sizeof key_data);
if (!parse_cshl (key_id, cfile))
return 0;
key = auth_key_lookup (key_id);
token = peek_token (&val, cfile);
if (token == SEMI) {
if (!key)
parse_warn (cfile, "reference to undefined key %s",
print_hex_1 (key_id -> len,
key_id -> data,
key_id -> len));
data_string_forget (key_id, MDL);
} else {
if (!parse_cshl (&key_data, cfile))
return 0;
if (key) {
parse_warn (cfile, "redefinition of key %s",
print_hex_1 (key_id -> len,
key_id -> data,
key_id -> len));
old_key = key;
}
new_key = new_auth_key (key_data.len, MDL);
if (!new_key)
log_fatal ("No memory for key %s",
print_hex_1 (key_id -> len,
key_id -> data,
key_id -> len));
new_key -> length = key_data.len;
memcpy (new_key -> data, key_data.data, key_data.len);
enter_auth_key (key_id, new_key);
data_string_forget (&key_data, MDL);
}
parse_semi (cfile);
return key_id -> len ? 1 : 0;
}
int parse_warn (struct parse *cfile, const char *fmt, ...)
{
va_list list;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment