diff options
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/nsd/compat/b64_pton.c | 220 | ||||
-rw-r--r-- | usr.sbin/nsd/compat/inet_aton.c | 10 | ||||
-rw-r--r-- | usr.sbin/nsd/compat/strptime.c | 10 | ||||
-rw-r--r-- | usr.sbin/nsd/dns.c | 4 | ||||
-rw-r--r-- | usr.sbin/nsd/nsd.c | 4 | ||||
-rw-r--r-- | usr.sbin/nsd/rdata.c | 12 | ||||
-rw-r--r-- | usr.sbin/nsd/remote.c | 4 | ||||
-rw-r--r-- | usr.sbin/nsd/tsig.c | 106 | ||||
-rw-r--r-- | usr.sbin/nsd/util.c | 8 | ||||
-rw-r--r-- | usr.sbin/nsd/zlexer.lex | 64 | ||||
-rw-r--r-- | usr.sbin/nsd/zonec.c | 44 |
11 files changed, 331 insertions, 155 deletions
diff --git a/usr.sbin/nsd/compat/b64_pton.c b/usr.sbin/nsd/compat/b64_pton.c index b69bb21bfe3..0e4aafceb35 100644 --- a/usr.sbin/nsd/compat/b64_pton.c +++ b/usr.sbin/nsd/compat/b64_pton.c @@ -107,9 +107,9 @@ static const char Pad64 = '='; end of the data is performed using the '=' character. Since all base64 input is an integral number of octets, only the - ------------------------------------------------- + ------------------------------------------------- following cases can arise: - + (1) the final quantum of encoding input is an integral multiple of 24 bits; here, the final unit of encoded output will be an integral multiple of 4 characters @@ -128,65 +128,99 @@ static const char Pad64 = '='; it returns the number of data bytes stored at the target, or -1 on error. */ -int -b64_pton(char const *src, uint8_t *target, size_t targsize) +static int b64rmap_initialized = 0; +static uint8_t b64rmap[256]; + +static const uint8_t b64rmap_special = 0xf0; +static const uint8_t b64rmap_end = 0xfd; +static const uint8_t b64rmap_space = 0xfe; +static const uint8_t b64rmap_invalid = 0xff; + +/** + * Initializing the reverse map is not thread safe. + * Which is fine for NSD. For now... + **/ +static void +b64_initialize_rmap () +{ + int i; + + /* Null: end of string, stop parsing */ + b64rmap[0] = b64rmap_end; + + for (i = 1; i < 256; ++i) { + /* Whitespaces */ + if (isspace(i)) + b64rmap[i] = b64rmap_space; + /* Padding: stop parsing */ + else if (i == Pad64) + b64rmap[i] = b64rmap_end; + /* Non-base64 char */ + else + b64rmap[i] = b64rmap_invalid; + } + + /* Fill reverse mapping for base64 chars */ + for (i = 0; Base64[i] != '\0'; ++i) + b64rmap[(uint8_t)Base64[i]] = i; + + b64rmap_initialized = 1; +} + +static int +b64_pton_do(char const *src, uint8_t *target, size_t targsize) { int tarindex, state, ch; - char *pos; + uint8_t ofs; state = 0; tarindex = 0; - while ((ch = *src++) != '\0') { - if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ - continue; + while (1) + { + ch = *src++; + ofs = b64rmap[ch]; - if (ch == Pad64) - break; - - pos = strchr(Base64, ch); - if (pos == 0) { + if (ofs >= b64rmap_special) { + /* Ignore whitespaces */ + if (ofs == b64rmap_space) + continue; + /* End of base64 characters */ + if (ofs == b64rmap_end) + break; /* A non-base64 character. */ return (-1); } switch (state) { case 0: - if (target) { - if ((size_t)tarindex >= targsize) - return (-1); - target[tarindex] = (pos - Base64) << 2; - } + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = ofs << 2; state = 1; break; case 1: - if (target) { - if ((size_t)tarindex + 1 >= targsize) - return (-1); - target[tarindex] |= (pos - Base64) >> 4; - target[tarindex+1] = ((pos - Base64) & 0x0f) - << 4 ; - } + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= ofs >> 4; + target[tarindex+1] = (ofs & 0x0f) + << 4 ; tarindex++; state = 2; break; case 2: - if (target) { - if ((size_t)tarindex + 1 >= targsize) - return (-1); - target[tarindex] |= (pos - Base64) >> 2; - target[tarindex+1] = ((pos - Base64) & 0x03) - << 6; - } + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= ofs >> 2; + target[tarindex+1] = (ofs & 0x03) + << 6; tarindex++; state = 3; break; case 3: - if (target) { - if ((size_t)tarindex >= targsize) - return (-1); - target[tarindex] |= (pos - Base64); - } + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= ofs; tarindex++; state = 0; break; @@ -210,7 +244,7 @@ b64_pton(char const *src, uint8_t *target, size_t targsize) case 2: /* Valid, means one byte of info */ /* Skip any number of spaces. */ for ((void)NULL; ch != '\0'; ch = *src++) - if (!isspace((unsigned char)ch)) + if (b64rmap[ch] != b64rmap_space) break; /* Make sure there is another trailing = sign. */ if (ch != Pad64) @@ -225,7 +259,7 @@ b64_pton(char const *src, uint8_t *target, size_t targsize) * whitespace after it? */ for ((void)NULL; ch != '\0'; ch = *src++) - if (!isspace((unsigned char)ch)) + if (b64rmap[ch] != b64rmap_space) return (-1); /* @@ -234,7 +268,7 @@ b64_pton(char const *src, uint8_t *target, size_t targsize) * zeros. If we don't check them, they become a * subliminal channel. */ - if (target && target[tarindex] != 0) + if (target[tarindex] != 0) return (-1); } } else { @@ -248,3 +282,109 @@ b64_pton(char const *src, uint8_t *target, size_t targsize) return (tarindex); } + + +static int +b64_pton_len(char const *src) +{ + int tarindex, state, ch; + uint8_t ofs; + + state = 0; + tarindex = 0; + + while (1) + { + ch = *src++; + ofs = b64rmap[ch]; + + if (ofs >= b64rmap_special) { + /* Ignore whitespaces */ + if (ofs == b64rmap_space) + continue; + /* End of base64 characters */ + if (ofs == b64rmap_end) + break; + /* A non-base64 character. */ + return (-1); + } + + switch (state) { + case 0: + state = 1; + break; + case 1: + tarindex++; + state = 2; + break; + case 2: + tarindex++; + state = 3; + break; + case 3: + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (b64rmap[ch] != b64rmap_space) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (b64rmap[ch] != b64rmap_space) + return (-1); + + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} + + +int +b64_pton(char const *src, uint8_t *target, size_t targsize) +{ + if (!b64rmap_initialized) + b64_initialize_rmap (); + + if (target) + return b64_pton_do (src, target, targsize); + else + return b64_pton_len (src); +} diff --git a/usr.sbin/nsd/compat/inet_aton.c b/usr.sbin/nsd/compat/inet_aton.c index 7eb8e623d95..430f9b03d4f 100644 --- a/usr.sbin/nsd/compat/inet_aton.c +++ b/usr.sbin/nsd/compat/inet_aton.c @@ -99,7 +99,7 @@ inet_aton(const char *cp, struct in_addr *addr) * Values are specified as for C: * 0x=hex, 0=octal, isdigit=decimal. */ - if (!isdigit((int)c)) + if (!isdigit((unsigned char)c)) return (0); val = 0; base = 10; if (c == '0') { @@ -110,12 +110,12 @@ inet_aton(const char *cp, struct in_addr *addr) base = 8; } for (;;) { - if (isascii((int)c) && isdigit((int)c)) { + if (isascii((unsigned char)c) && isdigit((unsigned char)c)) { val = (val * base) + (c - '0'); c = *++cp; - } else if (base == 16 && isascii((int)c) && isxdigit((int)c)) { + } else if (base == 16 && isascii((unsigned char)c) && isxdigit((unsigned char)c)) { val = (val << 4) | - (c + 10 - (islower((int)c) ? 'a' : 'A')); + (c + 10 - (islower((unsigned char)c) ? 'a' : 'A')); c = *++cp; } else break; @@ -137,7 +137,7 @@ inet_aton(const char *cp, struct in_addr *addr) /* * Check for trailing characters. */ - if (c != '\0' && (!isascii((int)c) || !isspace((int)c))) + if (c != '\0' && (!isascii((unsigned char)c) || !isspace((unsigned char)c))) return (0); /* * Concoct the address according to diff --git a/usr.sbin/nsd/compat/strptime.c b/usr.sbin/nsd/compat/strptime.c index 0c61cc9008a..e6eb375918f 100644 --- a/usr.sbin/nsd/compat/strptime.c +++ b/usr.sbin/nsd/compat/strptime.c @@ -10,7 +10,7 @@ * - Does not properly processes year day * * LICENSE - * Copyright (c) 2008, NLnet Labs, Matthijs Mekking + * Copyright (c) 2008, NLnet Labs, Matthijs Mekking. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -91,7 +91,7 @@ str2int(const char **buf, int max) { int ret=0, count=0; - while (*buf[0] != '\0' && isdigit(*buf[0]) && count<max) { + while (*buf[0] != '\0' && isdigit((unsigned char)*buf[0]) && count<max) { ret = ret*10 + (*buf[0] - '0'); (*buf)++; count++; @@ -111,7 +111,7 @@ nsd_strptime(const char *s, const char *format, struct tm *tm) int c, alt_format, ret; int split_year = 0; - while ((c = *format) != '\0') { + while ((c = (unsigned char)*format) != '\0') { alt_format = 0; /* whitespace, literal or format */ @@ -119,7 +119,7 @@ nsd_strptime(const char *s, const char *format, struct tm *tm) /** whitespace matches zero or more whitespace characters in the * input string. **/ - while (isspace(*s)) + while (isspace((unsigned char)*s)) s++; } else if (c == '%') { /* format */ @@ -225,7 +225,7 @@ nsd_strptime(const char *s, const char *format, struct tm *tm) break; case 'n': /* arbitrary whitespace */ case 't': - while (isspace(*s)) + while (isspace((unsigned char)*s)) s++; break; case 'p': /* am pm */ diff --git a/usr.sbin/nsd/dns.c b/usr.sbin/nsd/dns.c index 5d80f8a11ba..b10a53810e5 100644 --- a/usr.sbin/nsd/dns.c +++ b/usr.sbin/nsd/dns.c @@ -891,7 +891,7 @@ rrtype_from_string(const char *name) if (strncasecmp(name, "TYPE", 4) != 0) return 0; - if (!isdigit((int)name[4])) + if (!isdigit((unsigned char)name[4])) return 0; /* The rest from the string must be a number. */ @@ -936,7 +936,7 @@ rrclass_from_string(const char *name) if (strncasecmp(name, "CLASS", 5) != 0) return 0; - if (!isdigit((int)name[5])) + if (!isdigit((unsigned char)name[5])) return 0; /* The rest from the string must be a number. */ diff --git a/usr.sbin/nsd/nsd.c b/usr.sbin/nsd/nsd.c index b8cfd3e3d59..dc37b31a3cd 100644 --- a/usr.sbin/nsd/nsd.c +++ b/usr.sbin/nsd/nsd.c @@ -829,11 +829,11 @@ main(int argc, char *argv[]) #ifdef HAVE_GETPWNAM /* Parse the username into uid and gid */ if (*nsd.username) { - if (isdigit((int)*nsd.username)) { + if (isdigit((unsigned char)*nsd.username)) { char *t; nsd.uid = strtol(nsd.username, &t, 10); if (*t != 0) { - if (*t != '.' || !isdigit((int)*++t)) { + if (*t != '.' || !isdigit((unsigned char)*++t)) { error("-u user or -u uid or -u uid.gid"); } nsd.gid = strtol(t, &t, 10); diff --git a/usr.sbin/nsd/rdata.c b/usr.sbin/nsd/rdata.c index 9d01c6c28dd..ec5d6ff4be0 100644 --- a/usr.sbin/nsd/rdata.c +++ b/usr.sbin/nsd/rdata.c @@ -98,9 +98,9 @@ rdata_dns_name_to_string(buffer_type *output, rdata_atom_type rdata, if (ch=='.' || ch==';' || ch=='(' || ch==')' || ch=='\\') { buffer_printf(output, "\\%c", (char) ch); - } else if (!isgraph((int)(unsigned char) ch)) { + } else if (!isgraph((unsigned char) ch)) { buffer_printf(output, "\\%03u", (unsigned int) ch); - } else if (isprint((int)(unsigned char) ch)) { + } else if (isprint((unsigned char) ch)) { buffer_printf(output, "%c", (char) ch); } else { buffer_printf(output, "\\%03u", (unsigned int) ch); @@ -127,7 +127,7 @@ rdata_text_to_string(buffer_type *output, rdata_atom_type rdata, buffer_printf(output, "\""); for (i = 1; i <= length; ++i) { char ch = (char) data[i]; - if (isprint((int)(unsigned char)ch)) { + if (isprint((unsigned char)ch)) { if (ch == '"' || ch == '\\') { buffer_printf(output, "\\"); } @@ -153,7 +153,7 @@ rdata_texts_to_string(buffer_type *output, rdata_atom_type rdata, buffer_printf(output, "\""); for (i = 1; i <= data[pos]; ++i) { char ch = (char) data[pos + i]; - if (isprint((int)(unsigned char)ch)) { + if (isprint((unsigned char)ch)) { if (ch == '"' || ch == '\\') { buffer_printf(output, "\\"); } @@ -179,7 +179,7 @@ rdata_long_text_to_string(buffer_type *output, rdata_atom_type rdata, buffer_printf(output, "\""); for (i = 0; i < length; ++i) { char ch = (char) data[i]; - if (isprint((int)(unsigned char)ch)) { + if (isprint((unsigned char)ch)) { if (ch == '"' || ch == '\\') { buffer_printf(output, "\\"); } @@ -201,7 +201,7 @@ rdata_tag_to_string(buffer_type *output, rdata_atom_type rdata, size_t i; for (i = 1; i <= length; ++i) { char ch = (char) data[i]; - if (isdigit((int)ch) || islower((int)ch)) + if (isdigit((unsigned char)ch) || islower((unsigned char)ch)) buffer_printf(output, "%c", ch); else return 0; } diff --git a/usr.sbin/nsd/remote.c b/usr.sbin/nsd/remote.c index 82b49990216..18ca7a64b88 100644 --- a/usr.sbin/nsd/remote.c +++ b/usr.sbin/nsd/remote.c @@ -731,7 +731,7 @@ static char* skipwhite(char* str) { /* EOS \0 is not a space */ - while( isspace(*str) ) + while( isspace((unsigned char)*str) ) str++; return str; } @@ -1036,7 +1036,7 @@ find_arg2(SSL* ssl, char* arg, char** arg2) if(as) { as[0]=0; *arg2 = as+1; - while(isspace(*as) && as > arg) + while(isspace((unsigned char)*as) && as > arg) as--; as[0]=0; return 1; diff --git a/usr.sbin/nsd/tsig.c b/usr.sbin/nsd/tsig.c index 8b4f3249470..316f477894d 100644 --- a/usr.sbin/nsd/tsig.c +++ b/usr.sbin/nsd/tsig.c @@ -1,5 +1,5 @@ /* - * tsig.h -- TSIG definitions (RFC 2845). + * tsig.c -- TSIG implementation (RFC 2845). * * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. * @@ -8,7 +8,7 @@ */ -#include <config.h> +#include "config.h" #include <stdlib.h> #include <ctype.h> @@ -17,16 +17,17 @@ #include "dns.h" #include "packet.h" #include "query.h" +#include "rbtree.h" static region_type *tsig_region; struct tsig_key_table { - struct tsig_key_table *next; + rbnode_t node; /* by dname */ tsig_key_type *key; }; typedef struct tsig_key_table tsig_key_table_type; -static tsig_key_table_type *tsig_key_table; +static rbtree_t *tsig_key_table; struct tsig_algorithm_table { @@ -37,18 +38,6 @@ typedef struct tsig_algorithm_table tsig_algorithm_table_type; static tsig_algorithm_table_type *tsig_algorithm_table; static size_t max_algo_digest_size = 0; -tsig_lookup_algorithm_table tsig_supported_algorithms[] = { - { TSIG_HMAC_MD5, "hmac-md5" }, -#ifdef HAVE_EVP_SHA1 - { TSIG_HMAC_SHA1, "hmac-sha1" }, -#endif /* HAVE_EVP_SHA1 */ - -#ifdef HAVE_EVP_SHA256 - { TSIG_HMAC_SHA256, "hmac-sha256" }, -#endif /* HAVE_EVP_SHA256 */ - { 0, NULL } -}; - static void tsig_digest_variables(tsig_record_type *tsig, int tsig_timers_only) { @@ -96,27 +85,53 @@ tsig_digest_variables(tsig_record_type *tsig, int tsig_timers_only) } } +static int +tree_dname_compare(const void* a, const void* b) +{ + return dname_compare((const dname_type*)a, (const dname_type*)b); +} + int tsig_init(region_type *region) { tsig_region = region; - tsig_key_table = NULL; + tsig_key_table = rbtree_create(region, &tree_dname_compare); tsig_algorithm_table = NULL; -#if defined(TSIG) && defined(HAVE_SSL) +#if defined(HAVE_SSL) return tsig_openssl_init(region); -#endif +#endif /* defined(HAVE_SSL) */ return 1; } void tsig_add_key(tsig_key_type *key) { - tsig_key_table_type *entry = (tsig_key_table_type *) region_alloc( + tsig_key_table_type *entry = (tsig_key_table_type *) region_alloc_zero( tsig_region, sizeof(tsig_key_table_type)); entry->key = key; - entry->next = tsig_key_table; - tsig_key_table = entry; + entry->node.key = entry->key->name; + (void)rbtree_insert(tsig_key_table, &entry->node); +} + +void +tsig_del_key(tsig_key_type *key) +{ + tsig_key_table_type *entry; + if(!key) return; + entry = (tsig_key_table_type*)rbtree_delete(tsig_key_table, key->name); + if(!entry) return; + region_recycle(tsig_region, entry, sizeof(tsig_key_table_type)); +} + +tsig_key_type* +tsig_find_key(const dname_type* name) +{ + tsig_key_table_type* entry; + entry = (tsig_key_table_type*)rbtree_search(tsig_key_table, name); + if(entry) + return entry->key; + return NULL; } void @@ -139,8 +154,8 @@ int tsig_strlowercmp(const char* str1, const char* str2) { while (str1 && str2 && *str1 != '\0' && *str2 != '\0') { - if(tolower((int)*str1) != tolower((int)*str2)) { - if(tolower((int)*str1) < tolower((int)*str2)) + if(tolower((unsigned char)*str1) != tolower((unsigned char)*str2)) { + if(tolower((unsigned char)*str1) < tolower((unsigned char)*str2)) return -1; return 1; } @@ -182,19 +197,6 @@ tsig_get_algorithm_by_name(const char *name) return NULL; } -/* - * Find an HMAC algorithm based on its id. - */ -tsig_algorithm_type * -tsig_get_algorithm_by_id(uint8_t alg) -{ - int i=0; - for (/*empty*/; tsig_supported_algorithms[i].id > 0; i++) { - if (tsig_supported_algorithms[i].id == alg) - return tsig_get_algorithm_by_name(tsig_supported_algorithms[i].short_name); - } - return NULL; -} const char * tsig_error(int error_code) @@ -248,11 +250,21 @@ tsig_create_record_custom(tsig_record_type *tsig, region_type *region, large_object_size, initial_cleanup_size, 0); tsig->context_region = region_create_custom(xalloc, free, chunk_size, large_object_size, initial_cleanup_size, 0); - region_add_cleanup(region, tsig_cleanup, tsig); + if(region) + region_add_cleanup(region, tsig_cleanup, tsig); tsig_init_record(tsig, NULL, NULL); } void +tsig_delete_record(tsig_record_type* tsig, region_type* region) +{ + if(region) + region_remove_cleanup(region, tsig_cleanup, tsig); + region_destroy(tsig->rr_region); + region_destroy(tsig->context_region); +} + +void tsig_init_record(tsig_record_type *tsig, tsig_algorithm_type *algorithm, tsig_key_type *key) @@ -272,7 +284,6 @@ tsig_init_record(tsig_record_type *tsig, int tsig_from_query(tsig_record_type *tsig) { - tsig_key_table_type *key_entry; tsig_key_type *key = NULL; tsig_algorithm_table_type *algorithm_entry; tsig_algorithm_type *algorithm = NULL; @@ -283,16 +294,7 @@ tsig_from_query(tsig_record_type *tsig) assert(!tsig->algorithm); assert(!tsig->key); - /* XXX: TODO: slow linear check for keyname */ - for (key_entry = tsig_key_table; - key_entry; - key_entry = key_entry->next) - { - if (dname_compare(tsig->key_name, key_entry->key->name) == 0) { - key = key_entry->key; - break; - } - } + key = (tsig_key_type*)tsig_find_key(tsig->key_name); for (algorithm_entry = tsig_algorithm_table; algorithm_entry; @@ -594,8 +596,6 @@ tsig_parse_rr(tsig_record_type *tsig, buffer_type *packet) tsig->rr_region, buffer_current(packet), tsig->other_size); buffer_skip(packet, tsig->other_size); tsig->status = TSIG_OK; - tsig->error_code = TSIG_ERROR_NOERROR; - return 1; } @@ -668,7 +668,7 @@ tsig_error_reply(tsig_record_type *tsig) void tsig_finalize() { -#if defined(TSIG) && defined(HAVE_SSL) +#if defined(HAVE_SSL) tsig_openssl_finalize(); -#endif +#endif /* defined(HAVE_SSL) */ } diff --git a/usr.sbin/nsd/util.c b/usr.sbin/nsd/util.c index 7d93f54b55b..7af07d0c65e 100644 --- a/usr.sbin/nsd/util.c +++ b/usr.sbin/nsd/util.c @@ -553,7 +553,7 @@ hex_pton(const char* src, uint8_t* target, size_t targsize) return -1; } while(*src) { - if(!isxdigit((int)src[0]) || !isxdigit((int)src[1])) + if(!isxdigit((unsigned char)src[0]) || !isxdigit((unsigned char)src[1])) return -1; *t++ = hexdigit_to_int(src[0]) * 16 + hexdigit_to_int(src[1]) ; @@ -658,7 +658,7 @@ b32_pton(const char *src, uint8_t *target, size_t tsize) if(p+5 >= tsize*8) return -1; - if(isspace(ch)) + if(isspace((unsigned char)ch)) continue; if(ch >= '0' && ch <= '9') @@ -690,13 +690,13 @@ strip_string(char *str) char *start = str; char *end = str + strlen(str) - 1; - while (isspace(*start)) + while (isspace((unsigned char)*start)) ++start; if (start > end) { /* Completely blank. */ str[0] = '\0'; } else { - while (isspace(*end)) + while (isspace((unsigned char)*end)) --end; *++end = '\0'; diff --git a/usr.sbin/nsd/zlexer.lex b/usr.sbin/nsd/zlexer.lex index 0d5ac7e0c9e..90a1df3741c 100644 --- a/usr.sbin/nsd/zlexer.lex +++ b/usr.sbin/nsd/zlexer.lex @@ -8,7 +8,7 @@ * */ -#include <config.h> +#include "config.h" #include <ctype.h> #include <errno.h> @@ -19,8 +19,6 @@ #include "dname.h" #include "zparser.h" -#define YY_NO_UNPUT - #if 0 #define LEXOUT(s) printf s /* used ONLY when debugging */ #else @@ -68,6 +66,23 @@ pop_parser_state(void) yy_switch_to_buffer(include_stack[include_stack_ptr]); } +static YY_BUFFER_STATE oldstate; +/* Start string scan */ +void +parser_push_stringbuf(char* str) +{ + oldstate = YY_CURRENT_BUFFER; + yy_switch_to_buffer(yy_scan_string(str)); +} + +void +parser_pop_stringbuf(void) +{ + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(oldstate); + oldstate = NULL; +} + #ifndef yy_set_bol /* compat definition, for flex 2.4.6 */ #define yy_set_bol(at_bol) \ { \ @@ -78,11 +93,23 @@ pop_parser_state(void) #endif %} +%option noinput +%option nounput +%{ +#ifndef YY_NO_UNPUT +#define YY_NO_UNPUT 1 +#endif +#ifndef YY_NO_INPUT +#define YY_NO_INPUT 1 +#endif +%} SPACE [ \t] LETTER [a-zA-Z] NEWLINE [\n\r] -ZONESTR [^ \t\n\r();.\"\$] +ZONESTR [^ \t\n\r();.\"\$]|\\.|\\\n +CHARSTR [^ \t\n\r();.]|\\.|\\\n +QUOTE \" DOLLAR \$ COMMENT ; DOT \. @@ -144,11 +171,13 @@ ANY [^\"\n\\]|\\. /* split the original yytext */ *tmp = '\0'; strip_string(yytext); - + dname = dname_parse(parser->region, tmp + 1); if (!dname) { zc_error("incorrect include origin '%s'", tmp + 1); + } else if (*(tmp + strlen(tmp + 1)) != '.') { + zc_error("$INCLUDE directive requires absolute domain name"); } else { origin = domain_table_insert( parser->db->domains, dname); @@ -242,6 +271,8 @@ ANY [^\"\n\\]|\\. <bitlabel><<EOF>> { zc_error("EOF inside bitlabel"); BEGIN(INITIAL); + yyrestart(yyin); /* this is so that lex does not give an internal err */ + yyterminate(); } <bitlabel>{BIT}* { yymore(); } <bitlabel>\n { ++parser->line; yymore(); } @@ -252,21 +283,23 @@ ANY [^\"\n\\]|\\. } /* Quoted strings. Strip leading and ending quotes. */ -\" { BEGIN(quotedstring); LEXOUT(("\" ")); } +{QUOTE} { BEGIN(quotedstring); LEXOUT(("\" ")); } <quotedstring><<EOF>> { zc_error("EOF inside quoted string"); BEGIN(INITIAL); + yyrestart(yyin); /* this is so that lex does not give an internal err */ + yyterminate(); } <quotedstring>{ANY}* { LEXOUT(("STR ")); yymore(); } <quotedstring>\n { ++parser->line; yymore(); } -<quotedstring>\" { +<quotedstring>{QUOTE} { LEXOUT(("\" ")); BEGIN(INITIAL); yytext[yyleng - 1] = '\0'; return parse_token(STR, yytext, &lexer_state); } -({ZONESTR}|\\.|\\\n)+ { +{ZONESTR}({CHARSTR})* { /* Any allowed word. */ return parse_token(STR, yytext, &lexer_state); } @@ -313,7 +346,7 @@ zoctet(char *text) if (s[0] != '\\') { /* Ordinary character. */ *p = *s; - } else if (isdigit((int)s[1]) && isdigit((int)s[2]) && isdigit((int)s[3])) { + } else if (isdigit((unsigned char)s[1]) && isdigit((unsigned char)s[2]) && isdigit((unsigned char)s[3])) { /* \DDD escape. */ int val = (hexdigit_to_int(s[1]) * 100 + hexdigit_to_int(s[2]) * 10 + @@ -341,8 +374,8 @@ zoctet(char *text) static int parse_token(int token, char *yytext, enum lexer_state *lexer_state) { - char *str = region_strdup(parser->rr_region, yytext); - size_t len = zoctet(str); + size_t len; + char *str; if (*lexer_state == EXPECT_OWNER) { *lexer_state = PARSING_OWNER; @@ -352,7 +385,7 @@ parse_token(int token, char *yytext, enum lexer_state *lexer_state) uint16_t rrclass; /* type */ - token = rrtype_to_token(str, &yylval.type); + token = rrtype_to_token(yytext, &yylval.type); if (token != 0) { *lexer_state = PARSING_RDATA; LEXOUT(("%d[%s] ", token, yytext)); @@ -360,7 +393,7 @@ parse_token(int token, char *yytext, enum lexer_state *lexer_state) } /* class */ - rrclass = rrclass_from_string(str); + rrclass = rrclass_from_string(yytext); if (rrclass != 0) { yylval.klass = rrclass; LEXOUT(("CLASS ")); @@ -368,13 +401,16 @@ parse_token(int token, char *yytext, enum lexer_state *lexer_state) } /* ttl */ - yylval.ttl = strtottl(str, &t); + yylval.ttl = strtottl(yytext, &t); if (*t == '\0') { LEXOUT(("TTL ")); return T_TTL; } } + str = region_strdup(parser->rr_region, yytext); + len = zoctet(str); + yylval.data.str = str; yylval.data.len = len; diff --git a/usr.sbin/nsd/zonec.c b/usr.sbin/nsd/zonec.c index 34391328ede..3a85ed48a7f 100644 --- a/usr.sbin/nsd/zonec.c +++ b/usr.sbin/nsd/zonec.c @@ -103,12 +103,12 @@ zparser_conv_hex(region_type *region, const char *hex, size_t len) while (*hex) { *t = 0; for (i = 16; i >= 1; i -= 15) { - if (isxdigit((int)*hex)) { + if (isxdigit((unsigned char)*hex)) { *t += hexdigit_to_int(*hex) * i; } else { zc_error_prev_line( "illegal hex character '%c'", - (int) *hex); + (int)(unsigned char) *hex); return NULL; } ++hex; @@ -144,12 +144,12 @@ zparser_conv_hex_length(region_type *region, const char *hex, size_t len) while (*hex) { *t = 0; for (i = 16; i >= 1; i -= 15) { - if (isxdigit((int)*hex)) { + if (isxdigit((unsigned char)*hex)) { *t += hexdigit_to_int(*hex) * i; } else { zc_error_prev_line( "illegal hex character '%c'", - (int) *hex); + (int)(unsigned char) *hex); return NULL; } ++hex; @@ -415,7 +415,7 @@ zparser_conv_ilnp64(region_type *region, const char *text) } else { /* Our grammar is stricter than the one accepted by * strtol. */ - c = (int) *ch; + c = (unsigned char) *ch; if (!isxdigit(c)) { zc_error_prev_line("ilnp64: invalid " "(non-hexadecimal) character %c", c); @@ -510,7 +510,7 @@ zparser_conv_eui(region_type *region, const char *text, size_t len) nnum = len/8; num = 1; for (ch = text; *ch != '\0'; ch++) { - int c = (int) *ch; + int c = (unsigned char) *ch; if (*ch == '-') { num++; } else if (!isxdigit(c)) { @@ -590,7 +590,7 @@ zparser_conv_tag(region_type *region, const char *text, size_t len) return NULL; } for (ptr = text; *ptr; ptr++) { - if (!isdigit(*ptr) && !islower(*ptr)) { + if (!isdigit((unsigned char)*ptr) && !islower((unsigned char)*ptr)) { zc_error_prev_line("invalid tag %s: contains invalid char %c", text, *ptr); return NULL; @@ -786,14 +786,14 @@ precsize_aton (char *cp, char **endptr) int exponent; int mantissa; - while (isdigit((int)*cp)) + while (isdigit((unsigned char)*cp)) mval = mval * 10 + hexdigit_to_int(*cp++); if (*cp == '.') { /* centimeters */ cp++; - if (isdigit((int)*cp)) { + if (isdigit((unsigned char)*cp)) { cmval = hexdigit_to_int(*cp++) * 10; - if (isdigit((int)*cp)) { + if (isdigit((unsigned char)*cp)) { cmval += hexdigit_to_int(*cp++); } } @@ -858,17 +858,17 @@ zparser_conv_loc(region_type *region, char *str) if (!parse_int(str, &str, °, "degrees", 0, 180)) return NULL; - if (!isspace((int)*str)) { + if (!isspace((unsigned char)*str)) { zc_error_prev_line("space expected after degrees"); return NULL; } ++str; /* Minutes? */ - if (isdigit((int)*str)) { + if (isdigit((unsigned char)*str)) { if (!parse_int(str, &str, &min, "minutes", 0, 60)) return NULL; - if (!isspace((int)*str)) { + if (!isspace((unsigned char)*str)) { zc_error_prev_line("space expected after minutes"); return NULL; } @@ -876,7 +876,7 @@ zparser_conv_loc(region_type *region, char *str) } /* Seconds? */ - if (isdigit((int)*str)) { + if (isdigit((unsigned char)*str)) { start = str; if (!parse_int(str, &str, &i, "seconds", 0, 60)) { return NULL; @@ -886,7 +886,7 @@ zparser_conv_loc(region_type *region, char *str) return NULL; } - if (!isspace((int)*str)) { + if (!isspace((unsigned char)*str)) { zc_error_prev_line("space expected after seconds"); return NULL; } @@ -929,7 +929,7 @@ zparser_conv_loc(region_type *region, char *str) if (lat != 0 && lon != 0) break; - if (!isspace((int)*str)) { + if (!isspace((unsigned char)*str)) { zc_error_prev_line("space expected after latitude/longitude"); return NULL; } @@ -942,7 +942,7 @@ zparser_conv_loc(region_type *region, char *str) return NULL; } - if (!isspace((int)*str)) { + if (!isspace((unsigned char)*str)) { zc_error_prev_line("space expected before altitude"); return NULL; } @@ -966,7 +966,7 @@ zparser_conv_loc(region_type *region, char *str) if (!parse_int(str + 1, &str, &i, "altitude fraction", 0, 99)) { return NULL; } - if (!isspace((int)*str) && *str != '\0' && *str != 'm') { + if (!isspace((unsigned char)*str) && *str != '\0' && *str != 'm') { zc_error_prev_line("altitude fraction must be a number"); return NULL; } @@ -975,7 +975,7 @@ zparser_conv_loc(region_type *region, char *str) zc_error_prev_line("altitude must be expressed in meters"); return NULL; } - if (!isspace((int)*str) && *str != '\0') + if (!isspace((unsigned char)*str) && *str != '\0') ++str; if (sscanf(start, "%lf", &d) != 1) { @@ -984,16 +984,16 @@ zparser_conv_loc(region_type *region, char *str) alt = (uint32_t) (10000000.0 + d * 100 + 0.5); - if (!isspace((int)*str) && *str != '\0') { + if (!isspace((unsigned char)*str) && *str != '\0') { zc_error_prev_line("unexpected character after altitude"); return NULL; } /* Now parse size, horizontal precision and vertical precision if any */ - for(i = 1; isspace((int)*str) && i <= 3; i++) { + for(i = 1; isspace((unsigned char)*str) && i <= 3; i++) { vszhpvp[i] = precsize_aton(str + 1, &str); - if (!isspace((int)*str) && *str != '\0') { + if (!isspace((unsigned char)*str) && *str != '\0') { zc_error_prev_line("invalid size or precision"); return NULL; } |