Пример #1
0
/**
 * @pre closure points to a valid isc_buffer
 * @pre isc_buffer has non-NULL mctx
 * @pre isc_buffer has NULL buffer OR a buffer allocated from mctx
 *
 * @post closure contains \0 terminated string which is concatenation
 *       of previous context and input text
 */
static void
buffer_append_str(void *closure, const char *text, int textlen) {
	isc_buffer_t *out_buf = closure;
	isc_region_t new_space;
	isc_region_t old_space;

	REQUIRE(ISC_BUFFER_VALID(out_buf));
	REQUIRE(out_buf->mctx != NULL);
	REQUIRE(text != NULL);

	/* Allocate sufficiently long output buffer. */
	isc_buffer_region(out_buf, &old_space);
	new_space.length = isc_buffer_length(out_buf) + textlen + 1;
	new_space.base = isc_mem_get(out_buf->mctx, new_space.length);
	RUNTIME_CHECK(new_space.base != NULL);
	isc_buffer_reinit(out_buf, new_space.base, new_space.length);
	if (old_space.base != NULL)
		isc_mem_put(out_buf->mctx, old_space.base, old_space.length);

	/* Append output text and \0-terminate it.
	 * Overwrite \0 at the end if needed. */
	if (isc_buffer_usedlength(out_buf) != 0)
		/* Previous string is \0 terminated, chop \0. */
		isc_buffer_subtract(out_buf, 1);
	isc_buffer_putstr(out_buf, text);
	isc_buffer_putuint8(out_buf, '\0');
}
Пример #2
0
static isc_result_t
grow_headerspace(isc_httpd_t *httpd) {
	char *newspace;
	unsigned int newlen;
	isc_region_t r;

	newlen = httpd->headerlen + HTTP_SENDGROW;
	if (newlen > HTTP_SEND_MAXLEN)
		return (ISC_R_NOSPACE);

	newspace = isc_mem_get(httpd->mgr->mctx, newlen);
	if (newspace == NULL)
		return (ISC_R_NOMEMORY);
	isc_buffer_region(&httpd->headerbuffer, &r);
	isc_buffer_reinit(&httpd->headerbuffer, newspace, newlen);

	isc_mem_put(httpd->mgr->mctx, r.base, r.length);

	return (ISC_R_SUCCESS);
}
Пример #3
0
/*
 * Perform an update-policy rule check against an external application
 * over a socket.
 *
 * This currently only supports local: for unix domain datagram sockets.
 *
 * Note that by using a datagram socket and creating a new socket each
 * time we avoid the need for locking and allow for parallel access to
 * the authorization server.
 */
isc_boolean_t
dns_ssu_external_match(dns_name_t *identity,
		       dns_name_t *signer, dns_name_t *name,
		       isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
		       const dst_key_t *key, isc_mem_t *mctx)
{
	char b_identity[DNS_NAME_FORMATSIZE];
	char b_signer[DNS_NAME_FORMATSIZE];
	char b_name[DNS_NAME_FORMATSIZE];
	char b_addr[ISC_NETADDR_FORMATSIZE];
	char b_type[DNS_RDATATYPE_FORMATSIZE];
	char b_key[DST_KEY_FORMATSIZE];
	isc_buffer_t *tkey_token = NULL;
	int fd;
	const char *sock_path;
	unsigned int req_len;
	isc_region_t token_region;
	unsigned char *data;
	isc_buffer_t buf;
	isc_uint32_t token_len = 0;
	isc_uint32_t reply;
	ssize_t ret;

	/* The identity contains local:/path/to/socket */
	dns_name_format(identity, b_identity, sizeof(b_identity));

	/* For now only local: is supported */
	if (strncmp(b_identity, "local:", 6) != 0) {
		ssu_e_log(3, "ssu_external: invalid socket path '%s'",
			  b_identity);
		return (ISC_FALSE);
	}
	sock_path = &b_identity[6];

	fd = ux_socket_connect(sock_path);
	if (fd == -1)
		return (ISC_FALSE);

	if (key != NULL) {
		dst_key_format(key, b_key, sizeof(b_key));
		tkey_token = dst_key_tkeytoken(key);
	} else
		b_key[0] = 0;

	if (tkey_token != NULL) {
		isc_buffer_region(tkey_token, &token_region);
		token_len = token_region.length;
	}

	/* Format the request elements */
	if (signer != NULL)
		dns_name_format(signer, b_signer, sizeof(b_signer));
	else
		b_signer[0] = 0;

	dns_name_format(name, b_name, sizeof(b_name));

	if (tcpaddr != NULL)
		isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
	else
		b_addr[0] = 0;

	dns_rdatatype_format(type, b_type, sizeof(b_type));

	/* Work out how big the request will be */
	req_len = sizeof(isc_uint32_t)     + /* Format version */
		  sizeof(isc_uint32_t)     + /* Length */
		  strlen(b_signer) + 1 + /* Signer */
		  strlen(b_name) + 1   + /* Name */
		  strlen(b_addr) + 1   + /* Address */
		  strlen(b_type) + 1   + /* Type */
		  strlen(b_key) + 1    + /* Key */
		  sizeof(isc_uint32_t)     + /* tkey_token length */
		  token_len;             /* tkey_token */


	/* format the buffer */
	data = isc_mem_allocate(mctx, req_len);
	if (data == NULL) {
		close(fd);
		return (ISC_FALSE);
	}

	isc_buffer_init(&buf, data, req_len);
	isc_buffer_putuint32(&buf, SSU_EXTERNAL_VERSION);
	isc_buffer_putuint32(&buf, req_len);

	/* Strings must be null-terminated */
	isc_buffer_putstr(&buf, b_signer);
	isc_buffer_putuint8(&buf, 0);
	isc_buffer_putstr(&buf, b_name);
	isc_buffer_putuint8(&buf, 0);
	isc_buffer_putstr(&buf, b_addr);
	isc_buffer_putuint8(&buf, 0);
	isc_buffer_putstr(&buf, b_type);
	isc_buffer_putuint8(&buf, 0);
	isc_buffer_putstr(&buf, b_key);
	isc_buffer_putuint8(&buf, 0);

	isc_buffer_putuint32(&buf, token_len);
	if (tkey_token && token_len != 0)
		isc_buffer_putmem(&buf, token_region.base, token_len);

	ENSURE(isc_buffer_availablelength(&buf) == 0);

	/* Send the request */
	ret = write(fd, data, req_len);
	isc_mem_free(mctx, data);
	if (ret != (ssize_t) req_len) {
		char strbuf[ISC_STRERRORSIZE];
		isc__strerror(errno, strbuf, sizeof(strbuf));
		ssu_e_log(3, "ssu_external: unable to send request - %s",
			  strbuf);
		close(fd);
		return (ISC_FALSE);
	}

	/* Receive the reply */
	ret = read(fd, &reply, sizeof(isc_uint32_t));
	if (ret != (ssize_t) sizeof(isc_uint32_t)) {
		char strbuf[ISC_STRERRORSIZE];
		isc__strerror(errno, strbuf, sizeof(strbuf));
		ssu_e_log(3, "ssu_external: unable to receive reply - %s",
			  strbuf);
		close(fd);
		return (ISC_FALSE);
	}

	close(fd);

	reply = ntohl(reply);

	if (reply == 0) {
		ssu_e_log(3, "ssu_external: denied external auth for '%s'",
			  b_name);
		return (ISC_FALSE);
	} else if (reply == 1) {
		ssu_e_log(3, "ssu_external: allowed external auth for '%s'",
			  b_name);
		return (ISC_TRUE);
	}

	ssu_e_log(3, "ssu_external: invalid reply 0x%08x", reply);

	return (ISC_FALSE);
}