summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorFrancis Dupont <fdupont@isc.org>2019-11-13 14:15:21 +0100
committerFrancis Dupont <fdupont@isc.org>2019-11-13 14:15:21 +0100
commit2bf9c0e7f0594687be090478ddcdb4fe6f7cd377 (patch)
tree0f8cf1a874d3eb9a5b8d768c9bb49549e9d863ab /common
parentf78a41b766d7fe99e82775e5852b649f97639c36 (diff)
downloadisc-dhcp-2bf9c0e7f0594687be090478ddcdb4fe6f7cd377.tar.gz
Diffstat (limited to 'common')
-rw-r--r--common/options.c85
-rw-r--r--common/parse.c52
2 files changed, 126 insertions, 11 deletions
diff --git a/common/options.c b/common/options.c
index 5b4f17d9..09723c60 100644
--- a/common/options.c
+++ b/common/options.c
@@ -35,6 +35,8 @@ struct option *vendor_cfg_option;
static int pretty_text(char **, char *, const unsigned char **,
const unsigned char *, int);
+static int pretty_dname(char **, char *, const unsigned char *,
+ const unsigned char *);
static int pretty_domain(char **, char *, const unsigned char **,
const unsigned char *);
static int prepare_option_buffer(struct universe *universe, struct buffer *bp,
@@ -1601,7 +1603,6 @@ format_has_text(format)
p = format;
while (*p != '\0') {
switch (*p++) {
- case 'd':
case 't':
return 1;
@@ -1615,6 +1616,7 @@ format_has_text(format)
case 'X':
case 'x':
case 'D':
+ case 'd':
return 0;
case 'c':
@@ -1857,8 +1859,23 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes)
numhunk = -2;
break;
case 'd':
- fmtbuf[l] = 't';
- /* Fall Through ! */
+ /* Should not be optional, array or compressed */
+ if ((option->format[i+1] == 'o') ||
+ (option->format[i+1] == 'a') ||
+ (option->format[i+1] == 'A') ||
+ (option->format[i+1] == 'c')) {
+ log_error("%s: Illegal use of domain name: %s",
+ option->name,
+ &(option->format[i-1]));
+ fmtbuf[l + 1] = 0;
+ }
+ k = MRns_name_len(data + len, data + hunksize);
+ if (k == -1) {
+ log_error("Invalid domain name.");
+ return "<error>";
+ }
+ hunksize += k;
+ break;
case 't':
fmtbuf[l + 1] = 0;
numhunk = -2;
@@ -2012,6 +2029,18 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes)
}
*op = 0;
break;
+ case 'd': /* RFC1035 format name */
+ k = MRns_name_len(data + len, dp);
+ /* Already tested... */
+ if (k == -1) {
+ log_error("invalid domain name.");
+ return "<error>";
+ }
+ pretty_dname(&op, endbuf-1, dp, data + len);
+ /* pretty_dname does not add the nul */
+ *op = '\0';
+ dp += k;
+ break;
case 'D': /* RFC1035 format name list */
for( ; dp < (data + len) ; dp += k) {
unsigned char nbuff[NS_MAXCDNAME];
@@ -4184,6 +4213,56 @@ pretty_text(char **dst, char *dend, const unsigned char **src,
}
static int
+pretty_dname(char **dst, char *dend, const unsigned char *src,
+ const unsigned char *send)
+{
+ const unsigned char *tend;
+ const unsigned char *srcp = src;
+ int count = 0;
+ int tsiz, status;
+
+ if (dst == NULL || dend == NULL || src == NULL || send == NULL ||
+ *dst == NULL || ((*dst + 1) > dend) || (src >= send))
+ return -1;
+
+ do {
+ /* Continue loop until end of src buffer. */
+ if (srcp >= send)
+ break;
+
+ /* Consume tag size. */
+ tsiz = *srcp;
+ srcp++;
+
+ /* At root, finis. */
+ if (tsiz == 0)
+ break;
+
+ tend = srcp + tsiz;
+
+ /* If the tag exceeds the source buffer, it's illegal.
+ * This should also trap compression pointers (which should
+ * not be in these buffers).
+ */
+ if (tend > send)
+ return -1;
+
+ /* dend-1 leaves room for a trailing dot and quote. */
+ status = pretty_escape(dst, dend-1, &srcp, tend);
+
+ if ((status == -1) || ((*dst + 1) > dend))
+ return -1;
+
+ **dst = '.';
+ (*dst)++;
+ count += status + 1;
+ }
+ while(1);
+
+ return count;
+}
+
+static int
pretty_domain(char **dst, char *dend, const unsigned char **src,
const unsigned char *send)
{
diff --git a/common/parse.c b/common/parse.c
index ff31e28c..eabf3ed2 100644
--- a/common/parse.c
+++ b/common/parse.c
@@ -5266,15 +5266,13 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
break;
case 'd': /* Domain name... */
- val = parse_host_name (cfile);
- if (!val) {
- parse_warn (cfile, "not a valid domain name.");
- skip_to_semi (cfile);
+ t = parse_domain_name(cfile);
+ if (!t) {
+ parse_warn(cfile, "not a valid domain name.");
+ skip_to_semi(cfile);
return 0;
}
- len = strlen (val);
- freeval = ISC_TRUE;
- goto make_string;
+ break;
case 't': /* Text string... */
token = next_token (&val, &len, cfile);
@@ -5286,7 +5284,6 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
}
return 0;
}
- make_string:
if (!make_const_data (&t, (const unsigned char *)val,
len, 1, 1, MDL))
log_fatal ("No memory for concatenation");
@@ -5938,3 +5935,42 @@ parse_domain_list(struct parse *cfile, int compress)
return t;
}
+struct expression *
+parse_domain_name(struct parse *cfile)
+{
+ const char *val;
+ struct expression *t = NULL;
+ unsigned len;
+ int result;
+ unsigned char buf[NS_MAXCDNAME];
+
+ val = parse_host_name(cfile);
+ if (!val) {
+ return NULL;
+ }
+ result = MRns_name_pton(val, buf, sizeof(buf));
+ /* No longer need val */
+ dfree((char *)val, MDL);
+
+ /* result == 1 means the input was fully qualified.
+ * result == 0 means the input wasn't.
+ * result == -1 means bad things.
+ */
+ if (result < 0) {
+ parse_warn(cfile, "Error assembling domain name: %m");
+ return NULL;
+ }
+
+ /* Compute the used length */
+ len = 0;
+ while (buf[len] != 0) {
+ len += buf[len] + 1;
+ }
+ /* Count the last label (0). */
+ len++;
+
+ if (!make_const_data(&t, buf, len, 1, 1, MDL))
+ log_fatal("No memory for domain name object.");
+
+ return t;
+}