예제 #1
0
/*
 * Puts resource record data on 'db'.
 */
isc_result_t
bdb_putrdata(DB *db, dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
{
	static DBT key, data;
	isc_buffer_t keybuf, databuf;
	char nametext[DNS_NAME_MAXTEXT];
	char rdatatext[MAX_RDATATEXT];

	isc_buffer_init(&keybuf, nametext, DNS_NAME_MAXTEXT);

	dns_name_totext(name, ISC_TRUE, &keybuf);

	key.data = isc_buffer_base(&keybuf);
	key.size = isc_buffer_usedlength(&keybuf);

	isc_buffer_init(&databuf, rdatatext, MAX_RDATATEXT);

	dns_ttl_totext(ttl, ISC_FALSE, &databuf);
	*(char *)isc_buffer_used(&databuf) = ' ';
	isc_buffer_add(&databuf, 1);

	dns_rdatatype_totext(rdata->type, &databuf);	/* XXX private data */
	*(char *)isc_buffer_used(&databuf) = ' ';
	isc_buffer_add(&databuf, 1);

	dns_rdata_totext(rdata, NULL, &databuf);

	data.data = isc_buffer_base(&databuf);
	data.size = isc_buffer_usedlength(&databuf);

	REQUIRE(db->put(db, NULL, &key, &data, 0) == 0);

	return ISC_R_SUCCESS;
}
예제 #2
0
isc_result_t
isc_httpd_addheader(isc_httpd_t *httpd, const char *name,
		    const char *val)
{
	isc_result_t result;
	unsigned int needlen;

	needlen = strlen(name); /* name itself */
	if (val != NULL)
		needlen += 2 + strlen(val); /* :<space> and val */
	needlen += 2; /* CRLF */

	while (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
		result = grow_headerspace(httpd);
		if (result != ISC_R_SUCCESS)
			return (result);
	}

	if (val != NULL)
		sprintf(isc_buffer_used(&httpd->headerbuffer),
			"%s: %s\r\n", name, val);
	else
		sprintf(isc_buffer_used(&httpd->headerbuffer),
			"%s\r\n", name);

	isc_buffer_add(&httpd->headerbuffer, needlen);

	return (ISC_R_SUCCESS);
}
예제 #3
0
isc_result_t
isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val) {
	isc_result_t result;
	unsigned int needlen;
	char buf[sizeof "18446744073709551616"];

	sprintf(buf, "%d", val);

	needlen = strlen(name); /* name itself */
	needlen += 2 + strlen(buf); /* :<space> and val */
	needlen += 2; /* CRLF */

	while (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
		result = grow_headerspace(httpd);
		if (result != ISC_R_SUCCESS)
			return (result);
	}

	sprintf(isc_buffer_used(&httpd->headerbuffer),
		"%s: %s\r\n", name, buf);

	isc_buffer_add(&httpd->headerbuffer, needlen);

	return (ISC_R_SUCCESS);
}
예제 #4
0
static isc_result_t
read_more(perf_datafile_t *dfile)
{
	unsigned char *data;
	size_t size;
	ssize_t n;
	isc_result_t result;

	if (!dfile->is_file && dfile->pipe_fd >= 0) {
		result = perf_os_waituntilreadable(dfile->fd, dfile->pipe_fd,
						   -1);
		if (result != ISC_R_SUCCESS)
			return (result);
	}

	isc_buffer_compact(&dfile->data);
	data = isc_buffer_used(&dfile->data);
	size = isc_buffer_availablelength(&dfile->data);

	n = read(dfile->fd, data, size);
	if (n < 0)
		return (ISC_R_FAILURE);

	isc_buffer_add(&dfile->data, n);
	nul_terminate(dfile);

	if (dfile->is_file &&
	    isc_buffer_usedlength(&dfile->data) == dfile->size)
		dfile->cached = ISC_TRUE;

	return (ISC_R_SUCCESS);
}
예제 #5
0
void
ns_os_shutdownmsg(char *command, isc_buffer_t *text) {
	char *input, *ptr;
	unsigned int n;
	pid_t pid;

	input = command;

	/* Skip the command name. */
	ptr = next_token(&input, " \t");
	if (ptr == NULL)
		return;

	ptr = next_token(&input, " \t");
	if (ptr == NULL)
		return;

	if (strcmp(ptr, "-p") != 0)
		return;

#ifdef HAVE_LINUXTHREADS
	pid = mainpid;
#else
	pid = getpid();
#endif

	n = snprintf((char *)isc_buffer_used(text),
		     isc_buffer_availablelength(text),
		     "pid: %ld", (long)pid);
	/* Only send a message if it is complete. */
	if (n > 0 && n < isc_buffer_availablelength(text))
		isc_buffer_add(text, n);
}
예제 #6
0
파일: buffer.c 프로젝트: each/bind9-collab
isc_result_t
isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
	unsigned char *base;
	unsigned int available;
	isc_result_t result;

	REQUIRE(ISC_BUFFER_VALID(b));
	REQUIRE(r != NULL);

	/*
	 * XXXDCL
	 */
	base = isc_buffer_used(b);
	available = isc_buffer_availablelength(b);
	if (ISC_UNLIKELY(b->autore)) {
		result = isc_buffer_reserve(&b, r->length);
		if (result != ISC_R_SUCCESS)
			return (result);
	}
	if (r->length > available)
		return (ISC_R_NOSPACE);
	memmove(base, r->base, r->length);
	b->used += r->length;

	return (ISC_R_SUCCESS);
}
예제 #7
0
static inline void
nul_terminate(perf_datafile_t *dfile)
{
	unsigned char *data;

	data = isc_buffer_used(&dfile->data);
	*data = '\0';
}
예제 #8
0
static void
rndc_recvdone(isc_task_t *task, isc_event_t *event) {
	isccc_sexpr_t *response = NULL;
	isccc_sexpr_t *data;
	isccc_region_t source;
	char *errormsg = NULL;
	char *textmsg = NULL;
	isc_result_t result;

	recvs--;

	if (ccmsg.result == ISC_R_EOF)
		fatal("connection to remote host closed\n"
		      "This may indicate that\n"
		      "* the remote server is using an older version of"
		      " the command protocol,\n"
		      "* this host is not authorized to connect,\n"
		      "* the clocks are not synchronized, or\n"
		      "* the key is invalid.");

	if (ccmsg.result != ISC_R_SUCCESS)
		fatal("recv failed: %s", isc_result_totext(ccmsg.result));

	source.rstart = isc_buffer_base(&ccmsg.buffer);
	source.rend = isc_buffer_used(&ccmsg.buffer);

	DO("parse message",
	   isccc_cc_fromwire(&source, &response, algorithm, &secret));

	data = isccc_alist_lookup(response, "_data");
	if (data == NULL)
		fatal("no data section in response");
	result = isccc_cc_lookupstring(data, "err", &errormsg);
	if (result == ISC_R_SUCCESS) {
		failed = ISC_TRUE;
		fprintf(stderr, "%s: '%s' failed: %s\n",
			progname, command, errormsg);
	}
	else if (result != ISC_R_NOTFOUND)
		fprintf(stderr, "%s: parsing response failed: %s\n",
			progname, isc_result_totext(result));

	result = isccc_cc_lookupstring(data, "text", &textmsg);
	if (result == ISC_R_SUCCESS) {
		if ((!quiet || failed) && strlen(textmsg) != 0U)
			fprintf(failed ? stderr : stdout, "%s\n", textmsg);
	} else if (result != ISC_R_NOTFOUND)
		fprintf(stderr, "%s: parsing response failed: %s\n",
			progname, isc_result_totext(result));

	isc_event_free(&event);
	isccc_sexpr_free(&response);
	if (sends == 0 && recvs == 0) {
		isc_socket_detach(&sock);
		isc_task_shutdown(task);
		RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
	}
}
예제 #9
0
isc_result_t
isccc_base64_decode(const char *cstr, isccc_region_t *target) {
	isc_buffer_t b;
	isc_result_t result;

	isc_buffer_init(&b, target->rstart, target->rend - target->rstart);
	result = isc_base64_decodestring(cstr, &b);
	if (result != ISC_R_SUCCESS)
		return (result);
	target->rstart = isc_buffer_used(&b);
	return (ISC_R_SUCCESS);
}
예제 #10
0
static isc_result_t
hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
	isc_hmacmd5_t *hmacmd5ctx = dctx->opaque;
	unsigned char *digest;

	if (isc_buffer_availablelength(sig) < ISC_MD5_DIGESTLENGTH)
		return (ISC_R_NOSPACE);
	digest = isc_buffer_used(sig);
	isc_hmacmd5_sign(hmacmd5ctx, digest);
	isc_buffer_add(sig, ISC_MD5_DIGESTLENGTH);

	return (ISC_R_SUCCESS);
}
예제 #11
0
isc_result_t
perf_datafile_next(perf_datafile_t *dfile, isc_buffer_t *lines,
		   isc_boolean_t is_update)
{
	const char *current;
	isc_result_t result;

	LOCK(&dfile->lock);

	if (dfile->maxruns > 0 && dfile->maxruns == dfile->nruns) {
		result = ISC_R_EOF;
		goto done;
	}

	result = read_one_line(dfile, lines);
	if (result == ISC_R_EOF) {
		if (!dfile->read_any) {
			result = ISC_R_INVALIDFILE;
			goto done;
		}
		if (dfile->maxruns != dfile->nruns) {
			reopen_file(dfile);
			result = read_one_line(dfile, lines);

		}
	}
	if (result != ISC_R_SUCCESS) {
		goto done;
	}
	dfile->read_any = ISC_TRUE;

	if (is_update) {
		while (ISC_TRUE) {
			current = isc_buffer_used(lines);
			result = read_one_line(dfile, lines);
			if (result == ISC_R_EOF &&
			    dfile->maxruns != dfile->nruns) {
				reopen_file(dfile);
			}
			if (result != ISC_R_SUCCESS ||
			    strcasecmp(current, "send") == 0)
				break;
		};
	}

	result = ISC_R_SUCCESS;
 done:
	UNLOCK(&dfile->lock);
	return (result);
}
예제 #12
0
isc_result_t
isc_httpd_endheaders(isc_httpd_t *httpd) {
	isc_result_t result;

	while (isc_buffer_availablelength(&httpd->headerbuffer) < 2) {
		result = grow_headerspace(httpd);
		if (result != ISC_R_SUCCESS)
			return (result);
	}

	sprintf(isc_buffer_used(&httpd->headerbuffer), "\r\n");
	isc_buffer_add(&httpd->headerbuffer, 2);

	return (ISC_R_SUCCESS);
}
예제 #13
0
static inline isc_result_t
fromwire_naptr(ARGS_FROMWIRE) {
	dns_name_t name;
	isc_region_t sr;
	unsigned char *regex;

	REQUIRE(type == dns_rdatatype_naptr);

	UNUSED(type);
	UNUSED(rdclass);

	dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);

	dns_name_init(&name, NULL);

	/*
	 * Order, preference.
	 */
	isc_buffer_activeregion(source, &sr);
	if (sr.length < 4)
		return (ISC_R_UNEXPECTEDEND);
	RETERR(mem_tobuffer(target, sr.base, 4));
	isc_buffer_forward(source, 4);

	/*
	 * Flags.
	 */
	RETERR(txt_fromwire(source, target));

	/*
	 * Service.
	 */
	RETERR(txt_fromwire(source, target));

	/*
	 * Regexp.
	 */
	regex = isc_buffer_used(target);
	RETERR(txt_fromwire(source, target));
	RETERR(txt_valid_regex(regex));

	/*
	 * Replacement.
	 */
	return (dns_name_fromwire(&name, source, dctx, options, target));
}
예제 #14
0
isc_result_t
isccc_base64_encode(isccc_region_t *source, int wordlength,
		  const char *wordbreak, isccc_region_t *target)
{
	isc_region_t sr;
	isc_buffer_t tb;
	isc_result_t result;

	sr.base = source->rstart;
	sr.length = source->rend - source->rstart;
	isc_buffer_init(&tb, target->rstart, target->rend - target->rstart);

	result = isc_base64_totext(&sr, wordlength, wordbreak, &tb);
	if (result != ISC_R_SUCCESS)
		return (result);
	source->rstart = source->rend;
	target->rstart = isc_buffer_used(&tb);
	return (ISC_R_SUCCESS);
}
예제 #15
0
파일: buffer.c 프로젝트: Gradwell/bind9
void
isc__buffer_putstr(isc_buffer_t *b, const char *source) {
	unsigned int l;
	unsigned char *cp;

	REQUIRE(ISC_BUFFER_VALID(b));
	REQUIRE(source != NULL);

	/*
	 * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
	 */
	l = strlen(source);

	REQUIRE(l <= isc_buffer_availablelength(b));

	cp = isc_buffer_used(b);
	memcpy(cp, source, l);
	b->used += l;
}
예제 #16
0
파일: buffer.c 프로젝트: Gradwell/bind9
isc_result_t
isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
	unsigned char *base;
	unsigned int available;

	REQUIRE(ISC_BUFFER_VALID(b));
	REQUIRE(r != NULL);

	/*
	 * XXXDCL
	 */
	base = isc_buffer_used(b);
	available = isc_buffer_availablelength(b);
	if (r->length > available)
		return (ISC_R_NOSPACE);
	memcpy(base, r->base, r->length);
	b->used += r->length;

	return (ISC_R_SUCCESS);
}
예제 #17
0
isc_result_t
isc_httpd_response(isc_httpd_t *httpd) {
	isc_result_t result;
	unsigned int needlen;

	needlen = strlen(httpd->protocol) + 1; /* protocol + space */
	needlen += 3 + 1;  /* room for response code, always 3 bytes */
	needlen += strlen(httpd->retmsg) + 2;  /* return msg + CRLF */

	while (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
		result = grow_headerspace(httpd);
		if (result != ISC_R_SUCCESS)
			return (result);
	}

	sprintf(isc_buffer_used(&httpd->headerbuffer), "%s %03d %s\r\n",
		httpd->protocol, httpd->retcode, httpd->retmsg);
	isc_buffer_add(&httpd->headerbuffer, needlen);

	return (ISC_R_SUCCESS);
}
예제 #18
0
파일: buffer.c 프로젝트: each/bind9-collab
void
isc_buffer_putdecint(isc_buffer_t *b, isc_int64_t v) {
	unsigned int l=0;
	unsigned char *cp;
	char buf[21];
	isc_result_t result;

	REQUIRE(ISC_BUFFER_VALID(b));

	/* xxxwpk do it more low-level way ? */
	l = snprintf(buf, 21, "%" ISC_PRINT_QUADFORMAT "d", v);
	RUNTIME_CHECK(l <= 21);
	if (ISC_UNLIKELY(b->autore)) {
		result = isc_buffer_reserve(&b, l);
		REQUIRE(result == ISC_R_SUCCESS);
	}
	REQUIRE(isc_buffer_availablelength(b) >= l);

	cp = isc_buffer_used(b);
	memmove(cp, buf, l);
	b->used += l;
}
예제 #19
0
static isc_result_t
buildfilename(dns_name_t *name, dns_keytag_t id,
	      unsigned int alg, unsigned int type,
	      const char *directory, isc_buffer_t *out)
{
	const char *suffix = "";
	unsigned int len;
	isc_result_t result;

	REQUIRE(out != NULL);
	if ((type & DST_TYPE_PRIVATE) != 0)
		suffix = ".private";
	else if (type == DST_TYPE_PUBLIC)
		suffix = ".key";
	if (directory != NULL) {
		if (isc_buffer_availablelength(out) < strlen(directory))
			return (ISC_R_NOSPACE);
		isc_buffer_putstr(out, directory);
		if (strlen(directory) > 0U &&
		    directory[strlen(directory) - 1] != '/')
			isc_buffer_putstr(out, "/");
	}
	if (isc_buffer_availablelength(out) < 1)
		return (ISC_R_NOSPACE);
	isc_buffer_putstr(out, "K");
	result = dns_name_tofilenametext(name, ISC_FALSE, out);
	if (result != ISC_R_SUCCESS)
		return (result);
	len = 1 + 3 + 1 + 5 + strlen(suffix) + 1;
	if (isc_buffer_availablelength(out) < len)
		return (ISC_R_NOSPACE);
	snprintf((char *) isc_buffer_used(out),
		 (int)isc_buffer_availablelength(out),
		 "+%03d+%05d%s", alg, id, suffix);
	isc_buffer_add(out, len);

	return (ISC_R_SUCCESS);
}
예제 #20
0
파일: buffer.c 프로젝트: each/bind9-collab
void
isc__buffer_putstr(isc_buffer_t *b, const char *source) {
	unsigned int l;
	unsigned char *cp;
	isc_result_t result;

	REQUIRE(ISC_BUFFER_VALID(b));
	REQUIRE(source != NULL);

	/*
	 * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
	 */
	l = strlen(source);
	if (ISC_UNLIKELY(b->autore)) {
		result = isc_buffer_reserve(&b, l);
		REQUIRE(result == ISC_R_SUCCESS);
	}
	REQUIRE(isc_buffer_availablelength(b) >= l);

	cp = isc_buffer_used(b);
	memmove(cp, source, l);
	b->used += l;
}
예제 #21
0
static inline isc_result_t
fromtext_naptr(ARGS_FROMTEXT) {
	isc_token_t token;
	dns_name_t name;
	isc_buffer_t buffer;
	unsigned char *regex;

	REQUIRE(type == dns_rdatatype_naptr);

	UNUSED(type);
	UNUSED(rdclass);
	UNUSED(callbacks);

	/*
	 * Order.
	 */
	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
				      ISC_FALSE));
	if (token.value.as_ulong > 0xffffU)
		RETTOK(ISC_R_RANGE);
	RETERR(uint16_tobuffer(token.value.as_ulong, target));

	/*
	 * Preference.
	 */
	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
				      ISC_FALSE));
	if (token.value.as_ulong > 0xffffU)
		RETTOK(ISC_R_RANGE);
	RETERR(uint16_tobuffer(token.value.as_ulong, target));

	/*
	 * Flags.
	 */
	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
				      ISC_FALSE));
	RETTOK(txt_fromtext(&token.value.as_textregion, target));

	/*
	 * Service.
	 */
	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
				      ISC_FALSE));
	RETTOK(txt_fromtext(&token.value.as_textregion, target));

	/*
	 * Regexp.
	 */
	regex = isc_buffer_used(target);
	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
				      ISC_FALSE));
	RETTOK(txt_fromtext(&token.value.as_textregion, target));
	RETTOK(txt_valid_regex(regex));

	/*
	 * Replacement.
	 */
	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
				      ISC_FALSE));
	dns_name_init(&name, NULL);
	buffer_fromregion(&buffer, &token.value.as_region);
	origin = (origin != NULL) ? origin : dns_rootname;
	RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
	return (ISC_R_SUCCESS);
}
예제 #22
0
isc_result_t
dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
		isc_buffer_t *target)
{
	unsigned char *ndata;
	char *tdata;
	unsigned int nlen, tlen;
	unsigned char c;
	unsigned int trem, count;
	unsigned int labels;
	isc_boolean_t saw_root = ISC_FALSE;

	/*
	 * This function assumes the name is in proper uncompressed
	 * wire format.
	 */
	REQUIRE(VALID_NAME(name));
	REQUIRE(ISC_BUFFER_VALID(target));

	ndata = name->ndata;
	nlen = name->length;
	labels = name->labels;
	tdata = isc_buffer_used(target);
	tlen = isc_buffer_availablelength(target);

	trem = tlen;

	if (labels == 0 && nlen == 0) {
		/*
		 * Special handling for an empty name.
		 */
		if (trem == 0)
			return (ISC_R_NOSPACE);

		/*
		 * The names of these booleans are misleading in this case.
		 * This empty name is not necessarily from the root node of
		 * the DNS root zone, nor is a final dot going to be included.
		 * They need to be set this way, though, to keep the "@"
		 * from being trounced.
		 */
		saw_root = ISC_TRUE;
		omit_final_dot = ISC_FALSE;
		*tdata++ = '@';
		trem--;

		/*
		 * Skip the while() loop.
		 */
		nlen = 0;
	} else if (nlen == 1 && labels == 1 && *ndata == '\0') {
		/*
		 * Special handling for the root label.
		 */
		if (trem == 0)
			return (ISC_R_NOSPACE);

		saw_root = ISC_TRUE;
		omit_final_dot = ISC_FALSE;
		*tdata++ = '.';
		trem--;

		/*
		 * Skip the while() loop.
		 */
		nlen = 0;
	}

	while (labels > 0 && nlen > 0 && trem > 0) {
		labels--;
		count = *ndata++;
		nlen--;
		if (count == 0) {
			saw_root = ISC_TRUE;
			break;
		}
		if (count < 64) {
			INSIST(nlen >= count);
			while (count > 0) {
				c = *ndata;
				switch (c) {
				case 0x22: /* '"' */
				case 0x28: /* '(' */
				case 0x29: /* ')' */
				case 0x2E: /* '.' */
				case 0x3B: /* ';' */
				case 0x5C: /* '\\' */
				/* Special modifiers in zone files. */
				case 0x40: /* '@' */
				case 0x24: /* '$' */
					if (trem < 2)
						return (ISC_R_NOSPACE);
					*tdata++ = '\\';
					CONVERTFROMASCII(c);
					*tdata++ = c;
					ndata++;
					trem -= 2;
					nlen--;
					break;
				default:
					if (c > 0x20 && c < 0x7f) {
						if (trem == 0)
							return (ISC_R_NOSPACE);
						CONVERTFROMASCII(c);
						*tdata++ = c;
						ndata++;
						trem--;
						nlen--;
					} else {
						char buf[5];
						if (trem < 4)
							return (ISC_R_NOSPACE);
						snprintf(buf, sizeof(buf),
							 "\\%03u", c);
						memcpy(tdata, buf, 4);
						tdata += 4;
						trem -= 4;
						ndata++;
						nlen--;
					}
				}
				count--;
			}
		} else {
			FATAL_ERROR(__FILE__, __LINE__,
				    "Unexpected label type %02x", count);
			/* NOTREACHED */
		}

		/*
		 * The following assumes names are absolute.  If not, we
		 * fix things up later.  Note that this means that in some
		 * cases one more byte of text buffer is required than is
		 * needed in the final output.
		 */
		if (trem == 0)
			return (ISC_R_NOSPACE);
		*tdata++ = '.';
		trem--;
	}

	if (nlen != 0 && trem == 0)
		return (ISC_R_NOSPACE);

	if (!saw_root || omit_final_dot)
		trem++;

	isc_buffer_add(target, tlen - trem);

	return (ISC_R_SUCCESS);
}
예제 #23
0
파일: rndc.c 프로젝트: pecharmin/bind9
static void
rndc_recvnonce(isc_task_t *task, isc_event_t *event) {
	isccc_sexpr_t *response = NULL;
	isccc_sexpr_t *_ctrl;
	isccc_region_t source;
	isc_result_t result;
	isc_uint32_t nonce;
	isccc_sexpr_t *request = NULL;
	isccc_time_t now;
	isc_region_t r;
	isccc_sexpr_t *data;
	isc_buffer_t b;

	recvs--;

	if (ccmsg.result == ISC_R_EOF)
		fatal("connection to remote host closed\n"
		      "This may indicate that\n"
		      "* the remote server is using an older version of"
		      " the command protocol,\n"
		      "* this host is not authorized to connect,\n"
		      "* the clocks are not synchronized,\n"
		      "* the key signing algorithm is incorrect, or\n"
		      "* the key is invalid.");

	if (ccmsg.result != ISC_R_SUCCESS)
		fatal("recv failed: %s", isc_result_totext(ccmsg.result));

	source.rstart = isc_buffer_base(&ccmsg.buffer);
	source.rend = isc_buffer_used(&ccmsg.buffer);

	DO("parse message",
	   isccc_cc_fromwire(&source, &response, algorithm, &secret));

	_ctrl = isccc_alist_lookup(response, "_ctrl");
	if (!isccc_alist_alistp(_ctrl))
		fatal("bad or missing ctrl section in response");
	nonce = 0;
	if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS)
		nonce = 0;

	isc_stdtime_get(&now);

	DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
						    now, now + 60, &request));
	data = isccc_alist_lookup(request, "_data");
	if (data == NULL)
		fatal("_data section missing");
	if (isccc_cc_definestring(data, "type", args) == NULL)
		fatal("out of memory");
	if (nonce != 0) {
		_ctrl = isccc_alist_lookup(request, "_ctrl");
		if (_ctrl == NULL)
			fatal("_ctrl section missing");
		if (isccc_cc_defineuint32(_ctrl, "_nonce", nonce) == NULL)
			fatal("out of memory");
	}

	isc_buffer_clear(databuf);
	/* Skip the length field (4 bytes) */
	isc_buffer_add(databuf, 4);

	DO("render message",
	   isccc_cc_towire(request, &databuf, algorithm, &secret));

	isc_buffer_init(&b, databuf->base, 4);
	isc_buffer_putuint32(&b, databuf->used - 4);

	r.base = databuf->base;
	r.length = databuf->used;

	isccc_ccmsg_cancelread(&ccmsg);
	DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
						    rndc_recvdone, NULL));
	recvs++;
	DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
					   NULL));
	sends++;

	isc_event_free(&event);
	isccc_sexpr_free(&response);
	return;
}
예제 #24
0
static void
control_recvmessage(isc_task_t *task, isc_event_t *event) {
	controlconnection_t *conn;
	controllistener_t *listener;
	controlkey_t *key;
	isccc_sexpr_t *request = NULL;
	isccc_sexpr_t *response = NULL;
	isc_uint32_t algorithm;
	isccc_region_t secret;
	isc_stdtime_t now;
	isc_buffer_t b;
	isc_region_t r;
	isc_buffer_t *text;
	isc_result_t result;
	isc_result_t eresult;
	isccc_sexpr_t *_ctrl;
	isccc_time_t sent;
	isccc_time_t exp;
	isc_uint32_t nonce;
	isccc_sexpr_t *data;

	REQUIRE(event->ev_type == ISCCC_EVENT_CCMSG);

	conn = event->ev_arg;
	listener = conn->listener;
	algorithm = DST_ALG_UNKNOWN;
	secret.rstart = NULL;
	text = NULL;

	/* Is the server shutting down? */
	if (listener->controls->shuttingdown)
		goto cleanup;

	if (conn->ccmsg.result != ISC_R_SUCCESS) {
		if (conn->ccmsg.result != ISC_R_CANCELED &&
		    conn->ccmsg.result != ISC_R_EOF)
			log_invalid(&conn->ccmsg, conn->ccmsg.result);
		goto cleanup;
	}

	request = NULL;

	for (key = ISC_LIST_HEAD(listener->keys);
	     key != NULL;
	     key = ISC_LIST_NEXT(key, link))
	{
		isccc_region_t ccregion;

		ccregion.rstart = isc_buffer_base(&conn->ccmsg.buffer);
		ccregion.rend = isc_buffer_used(&conn->ccmsg.buffer);
		secret.rstart = isc_mem_get(listener->mctx, key->secret.length);
		if (secret.rstart == NULL)
			goto cleanup;
		memmove(secret.rstart, key->secret.base, key->secret.length);
		secret.rend = secret.rstart + key->secret.length;
		algorithm = key->algorithm;
		result = isccc_cc_fromwire(&ccregion, &request,
					   algorithm, &secret);
		if (result == ISC_R_SUCCESS)
			break;
		isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
		if (result != ISCCC_R_BADAUTH) {
			log_invalid(&conn->ccmsg, result);
			goto cleanup;
		}
	}

	if (key == NULL) {
		log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
		goto cleanup;
	}

	/* We shouldn't be getting a reply. */
	if (isccc_cc_isreply(request)) {
		log_invalid(&conn->ccmsg, ISC_R_FAILURE);
		goto cleanup_request;
	}

	isc_stdtime_get(&now);

	/*
	 * Limit exposure to replay attacks.
	 */
	_ctrl = isccc_alist_lookup(request, "_ctrl");
	if (_ctrl == NULL) {
		log_invalid(&conn->ccmsg, ISC_R_FAILURE);
		goto cleanup_request;
	}

	if (isccc_cc_lookupuint32(_ctrl, "_tim", &sent) == ISC_R_SUCCESS) {
		if ((sent + CLOCKSKEW) < now || (sent - CLOCKSKEW) > now) {
			log_invalid(&conn->ccmsg, ISCCC_R_CLOCKSKEW);
			goto cleanup_request;
		}
	} else {
		log_invalid(&conn->ccmsg, ISC_R_FAILURE);
		goto cleanup_request;
	}

	/*
	 * Expire messages that are too old.
	 */
	if (isccc_cc_lookupuint32(_ctrl, "_exp", &exp) == ISC_R_SUCCESS &&
	    now > exp) {
		log_invalid(&conn->ccmsg, ISCCC_R_EXPIRED);
		goto cleanup_request;
	}

	/*
	 * Duplicate suppression (required for UDP).
	 */
	isccc_cc_cleansymtab(listener->controls->symtab, now);
	result = isccc_cc_checkdup(listener->controls->symtab, request, now);
	if (result != ISC_R_SUCCESS) {
		if (result == ISC_R_EXISTS)
			result = ISCCC_R_DUPLICATE;
		log_invalid(&conn->ccmsg, result);
		goto cleanup_request;
	}

	if (conn->nonce != 0 &&
	    (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS ||
	     conn->nonce != nonce)) {
		log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
		goto cleanup_request;
	}

	result = isc_buffer_allocate(listener->mctx, &text, 2 * 2048);
	if (result != ISC_R_SUCCESS)
		goto cleanup_request;

	/*
	 * Establish nonce.
	 */
	if (conn->nonce == 0) {
		while (conn->nonce == 0)
			isc_random_get(&conn->nonce);
		eresult = ISC_R_SUCCESS;
	} else
		eresult = ns_control_docommand(request, &text);

	result = isccc_cc_createresponse(request, now, now + 60, &response);
	if (result != ISC_R_SUCCESS)
		goto cleanup_request;

	data = isccc_alist_lookup(response, "_data");
	if (data != NULL) {
		if (isccc_cc_defineuint32(data, "result", eresult) == NULL)
			goto cleanup_response;
	}

	if (eresult != ISC_R_SUCCESS) {
		if (data != NULL) {
			const char *estr = isc_result_totext(eresult);
			if (isccc_cc_definestring(data, "err", estr) == NULL)
				goto cleanup_response;
		}
	}

	if (isc_buffer_usedlength(text) > 0) {
		if (data != NULL) {
			char *str = (char *)isc_buffer_base(text);
			if (isccc_cc_definestring(data, "text", str) == NULL)
				goto cleanup_response;
		}
	}

	_ctrl = isccc_alist_lookup(response, "_ctrl");
	if (_ctrl == NULL ||
	    isccc_cc_defineuint32(_ctrl, "_nonce", conn->nonce) == NULL)
		goto cleanup_response;

	if (conn->buffer == NULL) {
		result = isc_buffer_allocate(listener->mctx,
					     &conn->buffer, 2 * 2048);
		if (result != ISC_R_SUCCESS)
			goto cleanup_response;
	}

	isc_buffer_clear(conn->buffer);
	/* Skip the length field (4 bytes) */
	isc_buffer_add(conn->buffer, 4);

	result = isccc_cc_towire(response, &conn->buffer, algorithm, &secret);
	if (result != ISC_R_SUCCESS)
		goto cleanup_response;

	isc_buffer_init(&b, conn->buffer->base, 4);
	isc_buffer_putuint32(&b, conn->buffer->used - 4);

	r.base = conn->buffer->base;
	r.length = conn->buffer->used;

	result = isc_socket_send(conn->sock, &r, task, control_senddone, conn);
	if (result != ISC_R_SUCCESS)
		goto cleanup_response;
	conn->sending = ISC_TRUE;

	isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
	isccc_sexpr_free(&request);
	isccc_sexpr_free(&response);
	isc_buffer_free(&text);
	return;

 cleanup_response:
	isccc_sexpr_free(&response);

 cleanup_request:
	isccc_sexpr_free(&request);
	isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
	if (text != NULL)
		isc_buffer_free(&text);

 cleanup:
	isc_socket_detach(&conn->sock);
	isccc_ccmsg_invalidate(&conn->ccmsg);
	conn->ccmsg_valid = ISC_FALSE;
	maybe_free_connection(conn);
	maybe_free_listener(listener);
}
예제 #25
0
isc_result_t
dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
			isc_buffer_t *target)
{
	unsigned char *ndata;
	char *tdata;
	unsigned int nlen, tlen;
	unsigned char c;
	unsigned int trem, count;
	unsigned int labels;

	/*
	 * This function assumes the name is in proper uncompressed
	 * wire format.
	 */
	REQUIRE(VALID_NAME(name));
	REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
	REQUIRE(ISC_BUFFER_VALID(target));

	ndata = name->ndata;
	nlen = name->length;
	labels = name->labels;
	tdata = isc_buffer_used(target);
	tlen = isc_buffer_availablelength(target);

	trem = tlen;

	if (nlen == 1 && labels == 1 && *ndata == '\0') {
		/*
		 * Special handling for the root label.
		 */
		if (trem == 0)
			return (ISC_R_NOSPACE);

		omit_final_dot = ISC_FALSE;
		*tdata++ = '.';
		trem--;

		/*
		 * Skip the while() loop.
		 */
		nlen = 0;
	}

	while (labels > 0 && nlen > 0 && trem > 0) {
		labels--;
		count = *ndata++;
		nlen--;
		if (count == 0)
			break;
		if (count < 64) {
			INSIST(nlen >= count);
			while (count > 0) {
				c = *ndata;
				if ((c >= 0x30 && c <= 0x39) || /* digit */
				    (c >= 0x41 && c <= 0x5A) ||	/* uppercase */
				    (c >= 0x61 && c <= 0x7A) || /* lowercase */
				    c == 0x2D ||		/* hyphen */
				    c == 0x5F)			/* underscore */
				{
					if (trem == 0)
						return (ISC_R_NOSPACE);
					/* downcase */
					if (c >= 0x41 && c <= 0x5A)
						c += 0x20;
					CONVERTFROMASCII(c);
					*tdata++ = c;
					ndata++;
					trem--;
					nlen--;
				} else {
					if (trem < 3)
						return (ISC_R_NOSPACE);
					sprintf(tdata, "%%%02X", c);
					tdata += 3;
					trem -= 3;
					ndata++;
					nlen--;
				}
				count--;
			}
		} else {
			FATAL_ERROR(__FILE__, __LINE__,
				    "Unexpected label type %02x", count);
			/* NOTREACHED */
		}

		/*
		 * The following assumes names are absolute.  If not, we
		 * fix things up later.  Note that this means that in some
		 * cases one more byte of text buffer is required than is
		 * needed in the final output.
		 */
		if (trem == 0)
			return (ISC_R_NOSPACE);
		*tdata++ = '.';
		trem--;
	}

	if (nlen != 0 && trem == 0)
		return (ISC_R_NOSPACE);

	if (omit_final_dot)
		trem++;

	isc_buffer_add(target, tlen - trem);

	return (ISC_R_SUCCESS);
}
예제 #26
0
isc_result_t
dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
		  dns_decompress_t *dctx, unsigned int options,
		  isc_buffer_t *target)
{
	unsigned char *cdata, *ndata;
	unsigned int cused; /* Bytes of compressed name data used */
	unsigned int hops,  nused, labels, n, nmax;
	unsigned int current, new_current, biggest_pointer;
	isc_boolean_t done;
	fw_state state = fw_start;
	unsigned int c;
	unsigned char *offsets;
	dns_offsets_t odata;
	isc_boolean_t downcase;

	/*
	 * Copy the possibly-compressed name at source into target,
	 * decompressing it.
	 */

	REQUIRE(VALID_NAME(name));
	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
		(target == NULL && ISC_BUFFER_VALID(name->buffer)));

	downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);

	if (target == NULL && name->buffer != NULL) {
		target = name->buffer;
		isc_buffer_clear(target);
	}

	REQUIRE(dctx != NULL);
	REQUIRE(BINDABLE(name));

	INIT_OFFSETS(name, offsets, odata);

	/*
	 * Make 'name' empty in case of failure.
	 */
	MAKE_EMPTY(name);

	/*
	 * Initialize things to make the compiler happy; they're not required.
	 */
	n = 0;
	new_current = 0;

	/*
	 * Set up.
	 */
	labels = 0;
	hops = 0;
	done = ISC_FALSE;

	ndata = isc_buffer_used(target);
	nused = 0;

	/*
	 * Find the maximum number of uncompressed target name
	 * bytes we are willing to generate.  This is the smaller
	 * of the available target buffer length and the
	 * maximum legal domain name length (255).
	 */
	nmax = isc_buffer_availablelength(target);
	if (nmax > DNS_NAME_MAXWIRE)
		nmax = DNS_NAME_MAXWIRE;

	cdata = isc_buffer_current(source);
	cused = 0;

	current = source->current;
	biggest_pointer = current;

	/*
	 * Note:  The following code is not optimized for speed, but
	 * rather for correctness.  Speed will be addressed in the future.
	 */

	while (current < source->active && !done) {
		c = *cdata++;
		current++;
		if (hops == 0)
			cused++;

		switch (state) {
		case fw_start:
			if (c < 64) {
				offsets[labels] = nused;
				labels++;
				if (nused + c + 1 > nmax)
					goto full;
				nused += c + 1;
				*ndata++ = c;
				if (c == 0)
					done = ISC_TRUE;
				n = c;
				state = fw_ordinary;
			} else if (c >= 128 && c < 192) {
				/*
				 * 14 bit local compression pointer.
				 * Local compression is no longer an
				 * IETF draft.
				 */
				return (DNS_R_BADLABELTYPE);
			} else if (c >= 192) {
				/*
				 * Ordinary 14-bit pointer.
				 */
				if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
				    0)
					return (DNS_R_DISALLOWED);
				new_current = c & 0x3F;
				n = 1;
				state = fw_newcurrent;
			} else
				return (DNS_R_BADLABELTYPE);
			break;
		case fw_ordinary:
			if (downcase)
				c = maptolower[c];
			/* FALLTHROUGH */
		case fw_copy:
			*ndata++ = c;
			n--;
			if (n == 0)
				state = fw_start;
			break;
		case fw_newcurrent:
			new_current *= 256;
			new_current += c;
			n--;
			if (n != 0)
				break;
			if (new_current >= biggest_pointer)
				return (DNS_R_BADPOINTER);
			biggest_pointer = new_current;
			current = new_current;
			cdata = (unsigned char *)source->base +
				current;
			hops++;
			if (hops > DNS_POINTER_MAXHOPS)
				return (DNS_R_TOOMANYHOPS);
			state = fw_start;
			break;
		default:
			FATAL_ERROR(__FILE__, __LINE__,
				    "Unknown state %d", state);
			/* Does not return. */
		}
	}

	if (!done)
		return (ISC_R_UNEXPECTEDEND);

	name->ndata = (unsigned char *)target->base + target->used;
	name->labels = labels;
	name->length = nused;
	name->attributes |= DNS_NAMEATTR_ABSOLUTE;

	isc_buffer_forward(source, cused);
	isc_buffer_add(target, name->length);

	return (ISC_R_SUCCESS);

 full:
	if (nmax == DNS_NAME_MAXWIRE)
		/*
		 * The name did not fit even though we had a buffer
		 * big enough to fit a maximum-length name.
		 */
		return (DNS_R_NAMETOOLONG);
	else
		/*
		 * The name might fit if only the caller could give us a
		 * big enough buffer.
		 */
		return (ISC_R_NOSPACE);

}
예제 #27
0
static void
rndc_recvnonce(isc_task_t *task, isc_event_t *event) {
	isccc_sexpr_t *response = NULL;
	isccc_sexpr_t *_ctrl;
	isccc_region_t source;
	isc_result_t result;
	isc_uint32_t nonce;
	isccc_sexpr_t *request = NULL;
	isccc_time_t now;
	isc_region_t r;
	isccc_sexpr_t *data;
	isccc_region_t message;
	isc_uint32_t len;
	isc_buffer_t b;

	recvs--;

	if (ccmsg.result == ISC_R_EOF)
		fatal("connection to remote host closed\n"
		      "This may indicate that the remote server is using "
		      "an older version of \n"
		      "the command protocol, this host is not authorized "
		      "to connect,\nor the key is invalid.");

	if (ccmsg.result != ISC_R_SUCCESS)
		fatal("recv failed: %s", isc_result_totext(ccmsg.result));

	source.rstart = isc_buffer_base(&ccmsg.buffer);
	source.rend = isc_buffer_used(&ccmsg.buffer);

	DO("parse message", isccc_cc_fromwire(&source, &response, &secret));

	_ctrl = isccc_alist_lookup(response, "_ctrl");
	if (_ctrl == NULL)
		fatal("_ctrl section missing");
	nonce = 0;
	if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS)
		nonce = 0;

	isc_stdtime_get(&now);

	DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
						    now, now + 60, &request));
	data = isccc_alist_lookup(request, "_data");
	if (data == NULL)
		fatal("_data section missing");
	if (isccc_cc_definestring(data, "type", args) == NULL)
		fatal("out of memory");
	if (nonce != 0) {
		_ctrl = isccc_alist_lookup(request, "_ctrl");
		if (_ctrl == NULL)
			fatal("_ctrl section missing");
		if (isccc_cc_defineuint32(_ctrl, "_nonce", nonce) == NULL)
			fatal("out of memory");
	}
	message.rstart = databuf + 4;
	message.rend = databuf + sizeof(databuf);
	DO("render message", isccc_cc_towire(request, &message, &secret));
	len = sizeof(databuf) - REGION_SIZE(message);
	isc_buffer_init(&b, databuf, 4);
	isc_buffer_putuint32(&b, len - 4);
	r.length = len;
	r.base = databuf;

	isccc_ccmsg_cancelread(&ccmsg);
	DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
						    rndc_recvdone, NULL));
	recvs++;
	DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
					   NULL));
	sends++;

	isc_event_free(&event);
	isccc_sexpr_free(&response);
	return;
}
예제 #28
0
isc_result_t
dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
		  dns_name_t *origin, unsigned int options,
		  isc_buffer_t *target)
{
	unsigned char *ndata, *label;
	char *tdata;
	char c;
	ft_state state, kind;
	unsigned int value, count, tbcount, bitlength, maxlength;
	unsigned int n1, n2, vlen, tlen, nrem, nused, digits, labels, tused;
	isc_boolean_t done;
	unsigned char *offsets;
	dns_offsets_t odata;
	isc_boolean_t downcase;

	/*
	 * Convert the textual representation of a DNS name at source
	 * into uncompressed wire form stored in target.
	 *
	 * Notes:
	 *	Relative domain names will have 'origin' appended to them
	 *	unless 'origin' is NULL, in which case relative domain names
	 *	will remain relative.
	 */

	REQUIRE(VALID_NAME(name));
	REQUIRE(ISC_BUFFER_VALID(source));
	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
		(target == NULL && ISC_BUFFER_VALID(name->buffer)));
	
	downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);

	if (target == NULL && name->buffer != NULL) {
		target = name->buffer;
		isc_buffer_clear(target);
	}

	REQUIRE(BINDABLE(name));

	INIT_OFFSETS(name, offsets, odata);
	offsets[0] = 0;

	/*
	 * Initialize things to make the compiler happy; they're not required.
	 */
	n1 = 0;
	n2 = 0;
	vlen = 0;
	label = NULL;
	digits = 0;
	value = 0;
	count = 0;
	tbcount = 0;
	bitlength = 0;
	maxlength = 0;
	kind = ft_init;

	/*
	 * Make 'name' empty in case of failure.
	 */
	MAKE_EMPTY(name);

	/*
	 * Set up the state machine.
	 */
	tdata = (char *)source->base + source->current;
	tlen = isc_buffer_remaininglength(source);
	tused = 0;
	ndata = isc_buffer_used(target);
	nrem = isc_buffer_availablelength(target);
	if (nrem > 255)
		nrem = 255;
	nused = 0;
	labels = 0;
	done = ISC_FALSE;
	state = ft_init;

	while (nrem > 0 && tlen > 0 && !done) {
		c = *tdata++;
		tlen--;
		tused++;

		switch (state) {
		case ft_init:
			/*
			 * Is this the root name?
			 */
			if (c == '.') {
				if (tlen != 0)
					return (DNS_R_EMPTYLABEL);
				labels++;
				*ndata++ = 0;
				nrem--;
				nused++;
				done = ISC_TRUE;
				break;
			}
			if (c == '@' && tlen == 0) {
				state = ft_at;
				break;
			}

			/* FALLTHROUGH */
		case ft_start:
			label = ndata;
			ndata++;
			nrem--;
			nused++;
			count = 0;
			if (c == '\\') {
				state = ft_initialescape;
				break;
			}
			kind = ft_ordinary;
			state = ft_ordinary;
			if (nrem == 0)
				return (ISC_R_NOSPACE);
			/* FALLTHROUGH */
		case ft_ordinary:
			if (c == '.') {
				if (count == 0)
					return (DNS_R_EMPTYLABEL);
				*label = count;
				labels++;
				INSIST(labels <= 127);
				offsets[labels] = nused;
				if (tlen == 0) {
					labels++;
					*ndata++ = 0;
					nrem--;
					nused++;
					done = ISC_TRUE;
				}
				state = ft_start;
			} else if (c == '\\') {
				state = ft_escape;
			} else {
				if (count >= 63)
					return (DNS_R_LABELTOOLONG);
				count++;
				CONVERTTOASCII(c);
				if (downcase)
					c = maptolower[(int)c];
				*ndata++ = c;
				nrem--;
				nused++;
			}
			break;
		case ft_initialescape:
			if (c == '[') {
				/*
				 * This looks like a bitstring label, which
				 * was deprecated.  Intentionally drop it.
				 */
				return (DNS_R_BADLABELTYPE);
			}
			kind = ft_ordinary;
			state = ft_escape;
			/* FALLTHROUGH */
		case ft_escape:
			if (!isdigit(c & 0xff)) {
				if (count >= 63)
					return (DNS_R_LABELTOOLONG);
				count++;
				CONVERTTOASCII(c);
				if (downcase)
					c = maptolower[(int)c];
				*ndata++ = c;
				nrem--;
				nused++;
				state = ft_ordinary;
				break;
			}
			digits = 0;
			value = 0;
			state = ft_escdecimal;
			/* FALLTHROUGH */
		case ft_escdecimal:
			if (!isdigit(c & 0xff))
				return (DNS_R_BADESCAPE);
			value *= 10;
			value += digitvalue[(int)c];
			digits++;
			if (digits == 3) {
				if (value > 255)
					return (DNS_R_BADESCAPE);
				if (count >= 63)
					return (DNS_R_LABELTOOLONG);
				count++;
				if (downcase)
					value = maptolower[value];
				*ndata++ = value;
				nrem--;
				nused++;
				state = ft_ordinary;
			}
			break;
		default:
			FATAL_ERROR(__FILE__, __LINE__,
				    "Unexpected state %d", state);
			/* Does not return. */
		}
	}

	if (!done) {
		if (nrem == 0)
			return (ISC_R_NOSPACE);
		INSIST(tlen == 0);
		if (state != ft_ordinary && state != ft_at)
			return (ISC_R_UNEXPECTEDEND);
		if (state == ft_ordinary) {
			INSIST(count != 0);
			*label = count;
			labels++;
			INSIST(labels <= 127);
			offsets[labels] = nused;
		}
		if (origin != NULL) {
			if (nrem < origin->length)
				return (ISC_R_NOSPACE);
			label = origin->ndata;
			n1 = origin->length;
			nrem -= n1;
			while (n1 > 0) {
				n2 = *label++;
				INSIST(n2 <= 63); /* no bitstring support */
				*ndata++ = n2;
				n1 -= n2 + 1;
				nused += n2 + 1;
				while (n2 > 0) {
					c = *label++;
					if (downcase)
						c = maptolower[(int)c];
					*ndata++ = c;
					n2--;
				}
				labels++;
				if (n1 > 0) {
					INSIST(labels <= 127);
					offsets[labels] = nused;
				}
			}
			if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
				name->attributes |= DNS_NAMEATTR_ABSOLUTE;
		}
	} else
		name->attributes |= DNS_NAMEATTR_ABSOLUTE;

	name->ndata = (unsigned char *)target->base + target->used;
	name->labels = labels;
	name->length = nused;

	isc_buffer_forward(source, tused);
	isc_buffer_add(target, name->length);

	return (ISC_R_SUCCESS);
}
예제 #29
0
static inline isc_result_t
fromtext_hip(ARGS_FROMTEXT) {
	isc_token_t token;
	dns_name_t name;
	isc_buffer_t buffer;
	isc_buffer_t hit_len;
	isc_buffer_t key_len;
	unsigned char *start;
	size_t len;

	REQUIRE(type == dns_rdatatype_hip);

	UNUSED(type);
	UNUSED(rdclass);
	UNUSED(callbacks);

	/*
	 * Dummy HIT len.
	 */
	hit_len = *target;
	RETERR(uint8_tobuffer(0, target));

	/*
	 * Algorithm.
	 */
	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
				      ISC_FALSE));
	if (token.value.as_ulong > 0xffU)
		RETTOK(ISC_R_RANGE);
	RETERR(uint8_tobuffer(token.value.as_ulong, target));

	/*
	 * Dummy KEY len.
	 */
	key_len = *target;
	RETERR(uint16_tobuffer(0, target));

	/*
	 * HIT (base16).
	 */
	start = isc_buffer_used(target);
	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
				      ISC_FALSE));
	RETTOK(isc_hex_decodestring(DNS_AS_STR(token), target));

	/*
	 * Fill in HIT len.
	 */
	len = (unsigned char *)isc_buffer_used(target) - start;
	if (len > 0xffU)
		RETTOK(ISC_R_RANGE);
	RETERR(uint8_tobuffer((isc_uint32_t)len, &hit_len));

	/*
	 * Public key (base64).
	 */
	start = isc_buffer_used(target);
	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
				      ISC_FALSE));
	RETTOK(isc_base64_decodestring(DNS_AS_STR(token), target));

	/*
	 * Fill in KEY len.
	 */
	len = (unsigned char *)isc_buffer_used(target) - start;
	if (len > 0xffffU)
		RETTOK(ISC_R_RANGE);
	RETERR(uint16_tobuffer((isc_uint32_t)len, &key_len));

	/*
	 * Rendezvous Servers.
	 */
	dns_name_init(&name, NULL);
	do {
		RETERR(isc_lex_getmastertoken(lexer, &token,
					      isc_tokentype_string,
					      ISC_TRUE));
		if (token.type != isc_tokentype_string)
			break;
		buffer_fromregion(&buffer, &token.value.as_region);
		origin = (origin != NULL) ? origin : dns_rootname;
		RETTOK(dns_name_fromtext(&name, &buffer, origin, options,
					 target));
	} while (1);

	/*
	 * Let upper layer handle eol/eof.
	 */
	isc_lex_ungettoken(lexer, &token);

	return (ISC_R_SUCCESS);
}
예제 #30
0
static void
lookup_done(isc_task_t *task, isc_event_t *event) {
	ns_lwdclient_t *client;
	ns_lwdclientmgr_t *cm;
	dns_lookupevent_t *levent;
	lwres_buffer_t lwb;
	dns_name_t *name;
	dns_rdataset_t *rdataset;
	dns_rdataset_t *sigrdataset;
	isc_result_t result;
	lwres_result_t lwresult;
	isc_region_t r;
	isc_buffer_t b;
	lwres_grbnresponse_t *grbn;
	int i;

	REQUIRE(event != NULL);

	UNUSED(task);

	lwb.base = NULL;
	client = event->ev_arg;
	cm = client->clientmgr;
	INSIST(client->lookup == (dns_lookup_t *)event->ev_sender);

	levent = (dns_lookupevent_t *)event;
	grbn = &client->grbn;

	ns_lwdclient_log(50, "lookup event result = %s",
			 isc_result_totext(levent->result));

	result = levent->result;
	if (result != ISC_R_SUCCESS) {
		dns_lookup_destroy(&client->lookup);
		isc_event_free(&event);
		levent = NULL;

		switch (result) {
		case DNS_R_NXDOMAIN:
		case DNS_R_NCACHENXDOMAIN:
			result = ns_lwsearchctx_next(&client->searchctx);
			if (result != ISC_R_SUCCESS)
				lwresult = LWRES_R_NOTFOUND;
			else {
				start_lookup(client);
				return;
			}
			break;
		case DNS_R_NXRRSET:
		case DNS_R_NCACHENXRRSET:
			lwresult = LWRES_R_TYPENOTFOUND;
			break;
		default:
			lwresult = LWRES_R_FAILURE;
		}
		ns_lwdclient_errorpktsend(client, lwresult);
		return;
	}

	name = levent->name;
	b = client->recv_buffer;

	grbn->flags = 0;

	grbn->nrdatas = 0;
	grbn->rdatas = NULL;
	grbn->rdatalen = NULL;

	grbn->nsigs = 0;
	grbn->sigs = NULL;
	grbn->siglen = NULL;

	result = dns_name_totext(name, ISC_TRUE, &client->recv_buffer);
	if (result != ISC_R_SUCCESS)
		goto out;
	grbn->realname = (char *)isc_buffer_used(&b);
	grbn->realnamelen = isc_buffer_usedlength(&client->recv_buffer) -
			    isc_buffer_usedlength(&b);
	ns_lwdclient_log(50, "found name '%.*s'", grbn->realnamelen,
			 grbn->realname);

	grbn->rdclass = cm->view->rdclass;
	grbn->rdtype = client->rdtype;

	rdataset = levent->rdataset;
	if (rdataset != NULL) {
		/* The normal case */
		grbn->nrdatas = dns_rdataset_count(rdataset);
		grbn->rdatas = isc_mem_get(cm->mctx, grbn->nrdatas *
					   sizeof(unsigned char *));
		if (grbn->rdatas == NULL)
			goto out;
		grbn->rdatalen = isc_mem_get(cm->mctx, grbn->nrdatas *
					     sizeof(lwres_uint16_t));
		if (grbn->rdatalen == NULL)
			goto out;

		i = 0;
		result = fill_array(&i, rdataset, grbn->nrdatas, grbn->rdatas,
				    grbn->rdatalen);
		if (result != ISC_R_SUCCESS)
			goto out;
		INSIST(i == grbn->nrdatas);
		grbn->ttl = rdataset->ttl;
		if (rdataset->trust == dns_trust_secure)
			grbn->flags |= LWRDATA_VALIDATED;
	} else {
		/* The SIG query case */
		result = iterate_node(grbn, levent->db, levent->node,
				      cm->mctx);
		if (result != ISC_R_SUCCESS)
			goto out;
	}
	ns_lwdclient_log(50, "filled in %d rdata%s", grbn->nrdatas,
			 (grbn->nrdatas == 1) ? "" : "s");

	sigrdataset = levent->sigrdataset;
	if (sigrdataset != NULL) {
		grbn->nsigs = dns_rdataset_count(sigrdataset);
		grbn->sigs = isc_mem_get(cm->mctx, grbn->nsigs *
					 sizeof(unsigned char *));
		if (grbn->sigs == NULL)
			goto out;
		grbn->siglen = isc_mem_get(cm->mctx, grbn->nsigs *
					   sizeof(lwres_uint16_t));
		if (grbn->siglen == NULL)
			goto out;

		i = 0;
		result = fill_array(&i, sigrdataset, grbn->nsigs, grbn->sigs,
				    grbn->siglen);
		if (result != ISC_R_SUCCESS)
			goto out;
		INSIST(i == grbn->nsigs);
		ns_lwdclient_log(50, "filled in %d signature%s", grbn->nsigs,
				 (grbn->nsigs == 1) ? "" : "s");
	}

	/*
	 * Render the packet.
	 */
	client->pkt.recvlength = LWRES_RECVLENGTH;
	client->pkt.authtype = 0; /* XXXMLG */
	client->pkt.authlength = 0;
	client->pkt.result = LWRES_R_SUCCESS;

	lwresult = lwres_grbnresponse_render(cm->lwctx,
					     grbn, &client->pkt, &lwb);
	if (lwresult != LWRES_R_SUCCESS)
		goto out;

	isc_mem_put(cm->mctx, grbn->rdatas,
		    grbn->nrdatas * sizeof(unsigned char *));
	isc_mem_put(cm->mctx, grbn->rdatalen,
		    grbn->nrdatas * sizeof(lwres_uint16_t));

	if (grbn->sigs != NULL)
		isc_mem_put(cm->mctx, grbn->sigs,
			    grbn->nsigs * sizeof(unsigned char *));
	if (grbn->siglen != NULL)
		isc_mem_put(cm->mctx, grbn->siglen,
			    grbn->nsigs * sizeof(lwres_uint16_t));

	r.base = lwb.base;
	r.length = lwb.used;
	client->sendbuf = r.base;
	client->sendlength = r.length;
	result = ns_lwdclient_sendreply(client, &r);
	if (result != ISC_R_SUCCESS)
		goto out2;

	NS_LWDCLIENT_SETSEND(client);

	dns_lookup_destroy(&client->lookup);
	isc_event_free(&event);

	return;

 out:
	if (grbn->rdatas != NULL)
		isc_mem_put(cm->mctx, grbn->rdatas,
			    grbn->nrdatas * sizeof(unsigned char *));
	if (grbn->rdatalen != NULL)
		isc_mem_put(cm->mctx, grbn->rdatalen,
			    grbn->nrdatas * sizeof(lwres_uint16_t));

	if (grbn->sigs != NULL)
		isc_mem_put(cm->mctx, grbn->sigs,
			    grbn->nsigs * sizeof(unsigned char *));
	if (grbn->siglen != NULL)
		isc_mem_put(cm->mctx, grbn->siglen,
			    grbn->nsigs * sizeof(lwres_uint16_t));
 out2:
	if (client->lookup != NULL)
		dns_lookup_destroy(&client->lookup);
	if (lwb.base != NULL)
		lwres_context_freemem(cm->lwctx, lwb.base, lwb.length);

		isc_event_free(&event);

	ns_lwdclient_log(50, "error constructing getrrsetbyname response");
	ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
}