Пример #1
0
/**
 * Generate list of all values as bracketed list.
 * This string might be fed into cfg parser.
 *
 * Caller has to deallocate resulting output buffer.
 */
isc_result_t
fwd_print_bracketed_values_buf(isc_mem_t *mctx, ldap_valuelist_t *values,
			      isc_buffer_t **string) {
	isc_result_t result;
	ldap_value_t *value;
	const char prefix[] = "{ ";
	const char suffix[] = "}";
	isc_buffer_t tmp_buf; /* hack: only the base buffer is allocated */

	REQUIRE(string != NULL && *string == NULL);

	isc_buffer_initnull(&tmp_buf);
	tmp_buf.mctx = mctx;

	buffer_append_str(&tmp_buf, prefix, 2);
	for (value = HEAD(*values);
	     value != NULL && value->value != NULL;
	     value = NEXT(value, link)) {
		buffer_append_str(&tmp_buf, value->value, strlen(value->value));
		buffer_append_str(&tmp_buf, "; ", 2);
	}
	buffer_append_str(&tmp_buf, suffix, 2);

	/* create and copy string from tmp to output buffer */
	CHECK(isc_buffer_allocate(mctx, string, tmp_buf.used));
	isc_buffer_putmem(*string, isc_buffer_base(&tmp_buf), tmp_buf.used);

cleanup:
	if (tmp_buf.base != NULL)
		isc_mem_put(mctx, tmp_buf.base, tmp_buf.length);
	return result;
}
Пример #2
0
static void
isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
	isc_region_t r;
	isc_result_t result;
	isc_httpd_t *httpd = ev->ev_arg;
	isc_socketevent_t *sev = (isc_socketevent_t *)ev;
	isc_httpdurl_t *url;
	isc_time_t now;
	char datebuf[32];  /* Only need 30, but safety first */

	ENTER("recv");

	INSIST(ISC_HTTPD_ISRECV(httpd));

	if (sev->result != ISC_R_SUCCESS) {
		NOTICE("recv destroying client");
		destroy_client(&httpd);
		goto out;
	}

	result = process_request(httpd, sev->n);
	if (result == ISC_R_NOTFOUND) {
		if (httpd->recvlen >= HTTP_RECVLEN - 1) {
			destroy_client(&httpd);
			goto out;
		}
		r.base = (unsigned char *)httpd->recvbuf + httpd->recvlen;
		r.length = HTTP_RECVLEN - httpd->recvlen - 1;
		/* check return code? */
		(void)isc_socket_recv(httpd->sock, &r, 1, task,
				      isc_httpd_recvdone, httpd);
		goto out;
	} else if (result != ISC_R_SUCCESS) {
		destroy_client(&httpd);
		goto out;
	}

	ISC_HTTPD_SETSEND(httpd);

	/*
	 * XXXMLG Call function here.  Provide an add-header function
	 * which will append the common headers to a response we generate.
	 */
	isc_buffer_initnull(&httpd->bodybuffer);
	isc_time_now(&now);
	isc_time_formathttptimestamp(&now, datebuf, sizeof(datebuf));
	url = ISC_LIST_HEAD(httpd->mgr->urls);
	while (url != NULL) {
		if (strcmp(httpd->url, url->url) == 0)
			break;
		url = ISC_LIST_NEXT(url, link);
	}
	if (url == NULL)
		result = httpd->mgr->render_404(httpd->url, NULL,
						httpd->querystring,
						NULL, NULL,
						&httpd->retcode,
						&httpd->retmsg,
						&httpd->mimetype,
						&httpd->bodybuffer,
						&httpd->freecb,
						&httpd->freecb_arg);
	else
		result = url->action(httpd->url, url,
				     httpd->querystring,
				     httpd->headers,
				     url->action_arg,
				     &httpd->retcode, &httpd->retmsg,
				     &httpd->mimetype, &httpd->bodybuffer,
				     &httpd->freecb, &httpd->freecb_arg);
	if (result != ISC_R_SUCCESS) {
		result = httpd->mgr->render_500(httpd->url, url,
						httpd->querystring,
						NULL, NULL,
						&httpd->retcode,
						&httpd->retmsg,
						&httpd->mimetype,
						&httpd->bodybuffer,
						&httpd->freecb,
						&httpd->freecb_arg);
		RUNTIME_CHECK(result == ISC_R_SUCCESS);
	}

	isc_httpd_response(httpd);
	isc_httpd_addheader(httpd, "Content-Type", httpd->mimetype);
	isc_httpd_addheader(httpd, "Date", datebuf);
	isc_httpd_addheader(httpd, "Expires", datebuf);

	if (url != NULL && url->isstatic) {
		char loadbuf[32];
		isc_time_formathttptimestamp(&url->loadtime,
					     loadbuf, sizeof(loadbuf));
		isc_httpd_addheader(httpd, "Last-Modified", loadbuf);
		isc_httpd_addheader(httpd, "Cache-Control: public", NULL);
	} else {
	isc_httpd_addheader(httpd, "Last-Modified", datebuf);
	isc_httpd_addheader(httpd, "Pragma: no-cache", NULL);
	isc_httpd_addheader(httpd, "Cache-Control: no-cache", NULL);
	}

	isc_httpd_addheader(httpd, "Server: libisc", NULL);
	isc_httpd_addheaderuint(httpd, "Content-Length",
				isc_buffer_usedlength(&httpd->bodybuffer));
	isc_httpd_endheaders(httpd);  /* done */

	ISC_LIST_APPEND(httpd->bufflist, &httpd->headerbuffer, link);
	/*
	 * Link the data buffer into our send queue, should we have any data
	 * rendered into it.  If no data is present, we won't do anything
	 * with the buffer.
	 */
	if (isc_buffer_length(&httpd->bodybuffer) > 0)
		ISC_LIST_APPEND(httpd->bufflist, &httpd->bodybuffer, link);

	/* check return code? */
	(void)isc_socket_sendv(httpd->sock, &httpd->bufflist, task,
			       isc_httpd_senddone, httpd);

 out:
	isc_event_free(&ev);
	EXIT("recv");
}
Пример #3
0
static void
isc_httpd_accept(isc_task_t *task, isc_event_t *ev) {
	isc_result_t result;
	isc_httpdmgr_t *httpdmgr = ev->ev_arg;
	isc_httpd_t *httpd;
	isc_region_t r;
	isc_socket_newconnev_t *nev = (isc_socket_newconnev_t *)ev;
	isc_sockaddr_t peeraddr;

	ENTER("accept");

	LOCK(&httpdmgr->lock);
	if (MSHUTTINGDOWN(httpdmgr)) {
		NOTICE("accept shutting down, goto out");
		goto out;
	}

	if (nev->result == ISC_R_CANCELED) {
		NOTICE("accept canceled, goto out");
		goto out;
	}

	if (nev->result != ISC_R_SUCCESS) {
		/* XXXMLG log failure */
		NOTICE("accept returned failure, goto requeue");
		goto requeue;
	}

	(void)isc_socket_getpeername(nev->newsocket, &peeraddr);
	if (httpdmgr->client_ok != NULL &&
	    !(httpdmgr->client_ok)(&peeraddr, httpdmgr->cb_arg)) {
		isc_socket_detach(&nev->newsocket);
		goto requeue;
	}

	httpd = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpd_t));
	if (httpd == NULL) {
		/* XXXMLG log failure */
		NOTICE("accept failed to allocate memory, goto requeue");
		isc_socket_detach(&nev->newsocket);
		goto requeue;
	}

	httpd->mgr = httpdmgr;
	ISC_LINK_INIT(httpd, link);
	ISC_LIST_APPEND(httpdmgr->running, httpd, link);
	ISC_HTTPD_SETRECV(httpd);
	httpd->sock = nev->newsocket;
	isc_socket_setname(httpd->sock, "httpd", NULL);
	httpd->flags = 0;

	/*
	 * Initialize the buffer for our headers.
	 */
	httpd->headerdata = isc_mem_get(httpdmgr->mctx, HTTP_SENDGROW);
	if (httpd->headerdata == NULL) {
		isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t));
		isc_socket_detach(&nev->newsocket);
		goto requeue;
	}
	httpd->headerlen = HTTP_SENDGROW;
	isc_buffer_init(&httpd->headerbuffer, httpd->headerdata,
			httpd->headerlen);

	ISC_LIST_INIT(httpd->bufflist);

	isc_buffer_initnull(&httpd->bodybuffer);
	reset_client(httpd);

	r.base = (unsigned char *)httpd->recvbuf;
	r.length = HTTP_RECVLEN - 1;
	result = isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone,
				 httpd);
	/* FIXME!!! */
	POST(result);
	NOTICE("accept queued recv on socket");

 requeue:
	result = isc_socket_accept(httpdmgr->sock, task, isc_httpd_accept,
				   httpdmgr);
	if (result != ISC_R_SUCCESS) {
		/* XXXMLG what to do?  Log failure... */
		NOTICE("accept could not reaccept due to failure");
	}

 out:
	UNLOCK(&httpdmgr->lock);

	httpdmgr_destroy(httpdmgr);

	isc_event_free(&ev);

	EXIT("accept");
}
Пример #4
0
/**
 * Convert LDAP DN to absolute DNS names.
 *
 * @param[in]  dn     LDAP DN with one or two idnsName components at the
 *                    beginning.
 * @param[out] target Absolute DNS name derived from the first two idnsNames.
 * @param[out] origin Absolute DNS name derived from the last idnsName
 *                    component of DN, i.e. zone. Can be NULL.
 * @param[out] iszone ISC_TRUE if DN points to zone object, ISC_FALSE otherwise.
 *
 * @code
 * Examples:
 * dn = "idnsName=foo.bar, idnsName=example.org., cn=dns, dc=example, dc=org"
 * target = "foo.bar.example.org."
 * origin = "example.org."
 *
 * dn = "idnsname=89, idnsname=4.34.10.in-addr.arpa, cn=dns, dc=example, dc=org"
 * target = "89.4.34.10.in-addr.arpa."
 * origin = "4.34.10.in-addr.arpa."
 *
 * dn = "idnsname=third.test., idnsname=test., cn=dns, dc=example, dc=org"
 * target = "third.test."
 * origin = "test."
 * @endcode
 */
isc_result_t
dn_to_dnsname(isc_mem_t *mctx, const char *dn_str, dns_name_t *target,
	      dns_name_t *otarget, isc_boolean_t *iszone)
{
	LDAPDN dn = NULL;
	LDAPRDN rdn = NULL;
	LDAPAVA *attr = NULL;
	int idx;
	int ret;

	DECLARE_BUFFERED_NAME(name);
	DECLARE_BUFFERED_NAME(origin);
	isc_buffer_t name_buf;
	isc_buffer_t origin_buf;
	isc_result_t result;

	REQUIRE(dn_str != NULL);
	REQUIRE(target != NULL);

	INIT_BUFFERED_NAME(name);
	INIT_BUFFERED_NAME(origin);
	isc_buffer_initnull(&name_buf);
	isc_buffer_initnull(&origin_buf);

	/* Example DN: cn=a+sn=b, ou=people */

	ret = ldap_str2dn(dn_str, &dn, LDAP_DN_FORMAT_LDAPV3);
	if (ret != LDAP_SUCCESS || dn == NULL) {
		log_bug("ldap_str2dn failed: %u", ret);
		CLEANUP_WITH(ISC_R_UNEXPECTED);
	}

	/* iterate over DN components: e.g. cn=a+sn=b */
	for (idx = 0; dn[idx] != NULL; idx++) {
		rdn = dn[idx];

		/* "iterate" over RDN components: e.g. cn=a */
		INSIST(rdn[0] != NULL); /* RDN without (attr=value)?! */
		if (rdn[1] != NULL) {
			log_bug("multi-valued RDNs are not supported");
			CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
		}

		/* attribute in current RDN component */
		attr = rdn[0];
		if ((attr->la_flags & LDAP_AVA_STRING) == 0) {
			log_error("non-string attribute detected: position %u",
				  idx);
			CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
		}

		if (strncasecmp("idnsName", attr->la_attr.bv_val,
				attr->la_attr.bv_len) == 0) {
			if (idx == 0) {
				isc_buffer_init(&name_buf,
						attr->la_value.bv_val,
						attr->la_value.bv_len);
				isc_buffer_add(&name_buf,
					       attr->la_value.bv_len);
			} else if (idx == 1) {
				isc_buffer_init(&origin_buf,
						attr->la_value.bv_val,
						attr->la_value.bv_len);
				isc_buffer_add(&origin_buf,
					       attr->la_value.bv_len);
			} else { /* more than two idnsNames?! */
				break;
			}
		} else { /* no match - idx holds position */
			break;
		}
	}

	/* filter out unsupported cases */
	if (idx <= 0) {
		log_error("no idnsName component found in DN");
		CLEANUP_WITH(ISC_R_UNEXPECTEDEND);
	} else if (idx == 1) { /* zone only */
		if (iszone != NULL)
			*iszone = ISC_TRUE;
		CHECK(dns_name_copy(dns_rootname, &origin, NULL));
		CHECK(dns_name_fromtext(&name, &name_buf, dns_rootname, 0, NULL));
	} else if (idx == 2) { /* owner and zone */
		if (iszone != NULL)
			*iszone = ISC_FALSE;
		CHECK(dns_name_fromtext(&origin, &origin_buf, dns_rootname, 0,
					NULL));
		CHECK(dns_name_fromtext(&name, &name_buf, &origin, 0, NULL));
		if (dns_name_issubdomain(&name, &origin) == ISC_FALSE) {
			log_error("out-of-zone data: first idnsName is not a "
				  "subdomain of the other");
			CLEANUP_WITH(DNS_R_BADOWNERNAME);
		} else if (dns_name_equal(&name, &origin) == ISC_TRUE) {
			log_error("attempt to redefine zone apex: first "
				  "idnsName equals to zone name");
			CLEANUP_WITH(DNS_R_BADOWNERNAME);
		}
	} else {
		log_error("unsupported number of idnsName components in DN: "
			  "%u components found", idx);
		CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
	}

cleanup:
	if (result == ISC_R_SUCCESS)
		result = dns_name_dupwithoffsets(&name, mctx, target);
	else
		log_error_r("failed to convert DN '%s' to DNS name", dn_str);

	if (result == ISC_R_SUCCESS && otarget != NULL)
		result = dns_name_dupwithoffsets(&origin, mctx, otarget);

	if (result != ISC_R_SUCCESS) {
		if (dns_name_dynamic(target))
			dns_name_free(target, mctx);
		if (otarget) {
			if (dns_name_dynamic(otarget))
				dns_name_free(otarget, mctx);
		}
	}

	if (dn != NULL)
		ldap_dnfree(dn);

	return result;
}
Пример #5
0
isc_result_t
fwd_print_list_buff(isc_mem_t *mctx, dns_forwarders_t *fwdrs,
			 isc_buffer_t **out_buf) {
	isc_result_t result;
	size_t list_len;
	isc_buffer_t *dummy_fwdr_buf = NULL; /* fully dynamic allocation */
	isc_buffer_t tmp_buf; /* hack: only the base buffer is allocated */

	cfg_parser_t *parser = NULL;
	cfg_obj_t *forwarders_cfg = NULL;
	const cfg_obj_t *faddresses;
	const cfg_listelt_t *fwdr_cfg; /* config representation */
	/* internal representation */
#if LIBDNS_VERSION_MAJOR < 140
	isc_sockaddr_t *fwdr_int;
#else /* LIBDNS_VERSION_MAJOR >= 140 */
	dns_forwarder_t *fwdr_int;
#endif

	isc_buffer_initnull(&tmp_buf);
	tmp_buf.mctx = mctx;
	CHECK(cfg_parser_create(mctx, dns_lctx, &parser));

	/* Create dummy string with list of IP addresses of the same length
	 * as the original list of forwarders. Parse this string to obtain
	 * nested cfg structures which will be filled with data for actual
	 * forwarders.
	 *
	 * This is nasty hack but it is easiest way to create list of cfg_objs
	 * I found.
	 */
	list_len = fwd_list_len(fwdrs);
	CHECK(fwd_list_gen_dummy_config_string(mctx,
					       list_len, &dummy_fwdr_buf));
	CHECK(cfg_parse_buffer(parser, dummy_fwdr_buf,
			       cfg_type_forwarders, &forwarders_cfg));

	/* Walk through internal representation and cfg representation and copy
	 * data from the internal one to cfg data structures.*/
	faddresses = cfg_tuple_get(forwarders_cfg, "addresses");
	for (fwdr_int = ISC_LIST_HEAD(
#if LIBDNS_VERSION_MAJOR < 140
			fwdrs->addrs
#else /* LIBDNS_VERSION_MAJOR >= 140 */
			fwdrs->fwdrs
#endif
			), fwdr_cfg = cfg_list_first(faddresses);
	     INSIST((fwdr_int == NULL) == (fwdr_cfg == NULL)), fwdr_int != NULL;
	     fwdr_int = ISC_LIST_NEXT(fwdr_int, link), fwdr_cfg = cfg_list_next(fwdr_cfg)) {
#if LIBDNS_VERSION_MAJOR < 140
		fwdr_cfg->obj->value.sockaddr = *fwdr_int;
#else /* LIBDNS_VERSION_MAJOR >= 140 */
		fwdr_cfg->obj->value.sockaddrdscp.sockaddr = fwdr_int->addr;
		fwdr_cfg->obj->value.sockaddrdscp.dscp = fwdr_int->dscp;
#endif
	}
	cfg_print(faddresses, buffer_append_str, &tmp_buf);

	/* create and copy string from tmp to output buffer */
	CHECK(isc_buffer_allocate(mctx, out_buf, tmp_buf.used));
	isc_buffer_putmem(*out_buf, isc_buffer_base(&tmp_buf),
			  isc_buffer_usedlength(&tmp_buf));

cleanup:
	if (forwarders_cfg != NULL)
		cfg_obj_destroy(parser, &forwarders_cfg);
	if (parser != NULL)
		cfg_parser_destroy(&parser);
	if (dummy_fwdr_buf != NULL) {
		if (tmp_buf.base != NULL)
			isc_mem_put(mctx, tmp_buf.base, tmp_buf.length);
		isc_buffer_free(&dummy_fwdr_buf);
	}

	return result;
}