Ejemplo n.º 1
0
/*
  decode/process data
*/
static NTSTATUS ldapsrv_decode(void *private_data, DATA_BLOB blob)
{
	NTSTATUS status;
	struct ldapsrv_connection *conn = talloc_get_type(private_data,
							  struct ldapsrv_connection);
	struct asn1_data *asn1 = asn1_init(conn);
	struct ldap_message *msg = talloc(conn, struct ldap_message);

	if (asn1 == NULL || msg == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	if (!asn1_load(asn1, blob)) {
		talloc_free(msg);
		talloc_free(asn1);
		return NT_STATUS_NO_MEMORY;
	}

	status = ldap_decode(asn1, samba_ldap_control_handlers(), msg);
	if (!NT_STATUS_IS_OK(status)) {
		asn1_free(asn1);
		return status;
	}

	data_blob_free(&blob);
	talloc_steal(conn, msg);
	asn1_free(asn1);

	ldapsrv_process_message(conn, msg);
	return NT_STATUS_OK;
}
Ejemplo n.º 2
0
/*
  process a decoded ldap message
*/
static void ldapsrv_process_message(struct ldapsrv_connection *conn,
				    struct ldap_message *msg)
{
	struct ldapsrv_call *call;
	NTSTATUS status;
	DATA_BLOB blob;

	call = talloc(conn, struct ldapsrv_call);
	if (!call) {
		ldapsrv_terminate_connection(conn, "no memory");
		return;		
	}

	call->request = talloc_steal(call, msg);
	call->conn = conn;
	call->replies = NULL;
	call->send_callback = NULL;
	call->send_private = NULL;

	/* make the call */
	status = ldapsrv_do_call(call);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(call);
		return;
	}

	blob = data_blob(NULL, 0);

	if (call->replies == NULL) {
		talloc_free(call);
		return;
	}

	/* build all the replies into a single blob */
	while (call->replies) {
		DATA_BLOB b;
		bool ret;

		msg = call->replies->msg;
		if (!ldap_encode(msg, samba_ldap_control_handlers(), &b, call)) {
			DEBUG(0,("Failed to encode ldap reply of type %d\n", msg->type));
			talloc_free(call);
			return;
		}

		ret = data_blob_append(call, &blob, b.data, b.length);
		data_blob_free(&b);

		talloc_set_name_const(blob.data, "Outgoing, encoded LDAP packet");

		if (!ret) {
			talloc_free(call);
			return;
		}

		DLIST_REMOVE(call->replies, call->replies);
	}

	packet_send_callback(conn->packet, blob, 
			     call->send_callback, call->send_private);
	talloc_free(call);
	return;
}
Ejemplo n.º 3
0
static void ldapsrv_call_process_done(struct tevent_req *subreq)
{
	struct ldapsrv_call *call =
		tevent_req_callback_data(subreq,
		struct ldapsrv_call);
	struct ldapsrv_connection *conn = call->conn;
	NTSTATUS status;
	DATA_BLOB blob = data_blob_null;

	conn->active_call = NULL;

	status = ldapsrv_process_call_recv(subreq);
	TALLOC_FREE(subreq);
	if (!NT_STATUS_IS_OK(status)) {
		ldapsrv_terminate_connection(conn, nt_errstr(status));
		return;
	}

	/* build all the replies into a single blob */
	while (call->replies) {
		DATA_BLOB b;
		bool ret;

		if (!ldap_encode(call->replies->msg, samba_ldap_control_handlers(), &b, call)) {
			DEBUG(0,("Failed to encode ldap reply of type %d\n",
				 call->replies->msg->type));
			ldapsrv_terminate_connection(conn, "ldap_encode failed");
			return;
		}

		ret = data_blob_append(call, &blob, b.data, b.length);
		data_blob_free(&b);

		talloc_set_name_const(blob.data, "Outgoing, encoded LDAP packet");

		if (!ret) {
			ldapsrv_terminate_connection(conn, "data_blob_append failed");
			return;
		}

		DLIST_REMOVE(call->replies, call->replies);
	}

	if (blob.length == 0) {
		TALLOC_FREE(call);

		ldapsrv_call_read_next(conn);
		return;
	}

	call->out_iov.iov_base = blob.data;
	call->out_iov.iov_len = blob.length;

	subreq = tstream_writev_queue_send(call,
					   conn->connection->event.ctx,
					   conn->sockets.active,
					   conn->sockets.send_queue,
					   &call->out_iov, 1);
	if (subreq == NULL) {
		ldapsrv_terminate_connection(conn, "stream_writev_queue_send failed");
		return;
	}
	tevent_req_set_callback(subreq, ldapsrv_call_writev_done, call);
}
Ejemplo n.º 4
0
static void ldapsrv_call_read_done(struct tevent_req *subreq)
{
	struct ldapsrv_connection *conn =
		tevent_req_callback_data(subreq,
		struct ldapsrv_connection);
	NTSTATUS status;
	struct ldapsrv_call *call;
	struct asn1_data *asn1;
	DATA_BLOB blob;

	call = talloc_zero(conn, struct ldapsrv_call);
	if (!call) {
		ldapsrv_terminate_connection(conn, "no memory");
		return;
	}

	call->conn = conn;

	status = tstream_read_pdu_blob_recv(subreq,
					    call,
					    &blob);
	TALLOC_FREE(subreq);
	if (!NT_STATUS_IS_OK(status)) {
		const char *reason;

		reason = talloc_asprintf(call, "ldapsrv_call_loop: "
					 "tstream_read_pdu_blob_recv() - %s",
					 nt_errstr(status));
		if (!reason) {
			reason = nt_errstr(status);
		}

		ldapsrv_terminate_connection(conn, reason);
		return;
	}

	asn1 = asn1_init(call);
	if (asn1 == NULL) {
		ldapsrv_terminate_connection(conn, "no memory");
		return;
	}

	call->request = talloc(call, struct ldap_message);
	if (call->request == NULL) {
		ldapsrv_terminate_connection(conn, "no memory");
		return;
	}

	if (!asn1_load(asn1, blob)) {
		ldapsrv_terminate_connection(conn, "asn1_load failed");
		return;
	}

	status = ldap_decode(asn1, samba_ldap_control_handlers(),
			     call->request);
	if (!NT_STATUS_IS_OK(status)) {
		ldapsrv_terminate_connection(conn, nt_errstr(status));
		return;
	}

	data_blob_free(&blob);


	/* queue the call in the global queue */
	subreq = ldapsrv_process_call_send(call,
					   conn->connection->event.ctx,
					   conn->service->call_queue,
					   call);
	if (subreq == NULL) {
		ldapsrv_terminate_connection(conn, "ldapsrv_process_call_send failed");
		return;
	}
	tevent_req_set_callback(subreq, ldapsrv_call_process_done, call);
	conn->active_call = subreq;
}