예제 #1
0
static void wbsrv_call_loop(struct tevent_req *subreq)
{
	struct wbsrv_connection *wbsrv_conn = tevent_req_callback_data(subreq,
				      struct wbsrv_connection);
	struct wbsrv_samba3_call *call;
	NTSTATUS status;

	call = talloc_zero(wbsrv_conn, struct wbsrv_samba3_call);
	if (call == NULL) {
		wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: "
				"no memory for wbsrv_samba3_call");
		return;
	}
	call->wbconn = wbsrv_conn;

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

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

		wbsrv_terminate_connection(wbsrv_conn, reason);
		return;
	}

	DEBUG(10,("Received winbind TCP packet of length %lu from %s\n",
		 (long) call->in.length,
		 tsocket_address_string(wbsrv_conn->conn->remote_address, call)));

	status = wbsrv_samba3_process(call);
	if (!NT_STATUS_IS_OK(status)) {
		const char *reason;

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

		wbsrv_terminate_connection(wbsrv_conn, reason);
		return;
	}

	/*
	 * The winbind pdu's has the length as 4 byte (initial_read_size),
	 * wbsrv_samba3_packet_full_request provides the pdu length then.
	 */
	subreq = tstream_read_pdu_blob_send(wbsrv_conn,
					    wbsrv_conn->conn->event.ctx,
					    wbsrv_conn->tstream,
					    4, /* initial_read_size */
					    wbsrv_samba3_packet_full_request,
					    wbsrv_conn);
	if (subreq == NULL) {
		wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: "
				"no memory for tstream_read_pdu_blob_send");
		return;
	}
	tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn);
}
예제 #2
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;
}
예제 #3
0
static void wreplsrv_call_loop(struct tevent_req *subreq)
{
	struct wreplsrv_in_connection *wrepl_conn = tevent_req_callback_data(subreq,
				      struct wreplsrv_in_connection);
	struct wreplsrv_in_call *call;
	NTSTATUS status;

	call = talloc_zero(wrepl_conn, struct wreplsrv_in_call);
	if (call == NULL) {
		wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_call_loop: "
				"no memory for wrepl_samba3_call");
		return;
	}
	call->wreplconn = wrepl_conn;

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

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

		wreplsrv_terminate_in_connection(wrepl_conn, reason);
		return;
	}

	DEBUG(10,("Received wrepl packet of length %lu from %s\n",
		 (long) call->in.length,
		 tsocket_address_string(wrepl_conn->conn->remote_address, call)));

	/* skip length header */
	call->in.data += 4;
	call->in.length -= 4;

	status = wreplsrv_process(wrepl_conn, &call);
	if (!NT_STATUS_IS_OK(status)) {
		const char *reason;

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

		wreplsrv_terminate_in_connection(wrepl_conn, reason);
		return;
	}

	/* We handed over the connection so we're done here */
	if (wrepl_conn->tstream == NULL) {
	    return;
	}

	/* Invalid WINS-Replication packet, we just ignore it */
	if (call == NULL) {
		goto noreply;
	}

	call->out_iov[0].iov_base = (char *) call->out.data;
	call->out_iov[0].iov_len = call->out.length;

	subreq = tstream_writev_queue_send(call,
					   wrepl_conn->conn->event.ctx,
					   wrepl_conn->tstream,
					   wrepl_conn->send_queue,
					   call->out_iov, 1);
	if (subreq == NULL) {
		wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_call_loop: "
				"no memory for tstream_writev_queue_send");
		return;
	}
	tevent_req_set_callback(subreq, wreplsrv_call_writev_done, call);

noreply:
	/*
	 * The wrepl pdu's has the length as 4 byte (initial_read_size),
	 *  provides the pdu length then.
	 */
	subreq = tstream_read_pdu_blob_send(wrepl_conn,
					    wrepl_conn->conn->event.ctx,
					    wrepl_conn->tstream,
					    4, /* initial_read_size */
					    packet_full_request_u32,
					    wrepl_conn);
	if (subreq == NULL) {
		wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_call_loop: "
				"no memory for tstream_read_pdu_blob_send");
		return;
	}
	tevent_req_set_callback(subreq, wreplsrv_call_loop, wrepl_conn);
}
예제 #4
0
파일: kdc.c 프로젝트: Arkhont/samba
static void kdc_tcp_call_loop(struct tevent_req *subreq)
{
	struct kdc_tcp_connection *kdc_conn = tevent_req_callback_data(subreq,
				      struct kdc_tcp_connection);
	struct kdc_tcp_call *call;
	NTSTATUS status;
	enum kdc_process_ret ret;

	call = talloc(kdc_conn, struct kdc_tcp_call);
	if (call == NULL) {
		kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
				"no memory for kdc_tcp_call");
		return;
	}
	call->kdc_conn = kdc_conn;

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

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

		kdc_tcp_terminate_connection(kdc_conn, reason);
		return;
	}

	DEBUG(10,("Received krb5 TCP packet of length %lu from %s\n",
		 (long) call->in.length,
		 tsocket_address_string(kdc_conn->conn->remote_address, call)));

	/* skip length header */
	call->in.data +=4;
	call->in.length -= 4;

	/* Call krb5 */
	ret = kdc_conn->kdc_socket->process(kdc_conn->kdc_socket->kdc,
					   call,
					   &call->in,
					   &call->out,
					   kdc_conn->conn->remote_address,
					   kdc_conn->conn->local_address,
					   0 /* Stream */);
	if (ret == KDC_PROCESS_FAILED) {
		kdc_tcp_terminate_connection(kdc_conn,
				"kdc_tcp_call_loop: process function failed");
		return;
	}

	if (ret == KDC_PROCESS_PROXY) {
		uint16_t port;

		if (!kdc_conn->kdc_socket->kdc->am_rodc) {
			kdc_tcp_terminate_connection(kdc_conn,
						     "kdc_tcp_call_loop: proxying requested when not RODC");
			return;
		}
		port = tsocket_address_inet_port(kdc_conn->conn->local_address);

		subreq = kdc_tcp_proxy_send(call,
					    kdc_conn->conn->event.ctx,
					    kdc_conn->kdc_socket->kdc,
					    port,
					    call->in);
		if (subreq == NULL) {
			kdc_tcp_terminate_connection(kdc_conn,
				"kdc_tcp_call_loop: kdc_tcp_proxy_send failed");
			return;
		}
		tevent_req_set_callback(subreq, kdc_tcp_call_proxy_done, call);
		return;
	}

	/* First add the length of the out buffer */
	RSIVAL(call->out_hdr, 0, call->out.length);
	call->out_iov[0].iov_base = (char *) call->out_hdr;
	call->out_iov[0].iov_len = 4;

	call->out_iov[1].iov_base = (char *) call->out.data;
	call->out_iov[1].iov_len = call->out.length;

	subreq = tstream_writev_queue_send(call,
					   kdc_conn->conn->event.ctx,
					   kdc_conn->tstream,
					   kdc_conn->send_queue,
					   call->out_iov, 2);
	if (subreq == NULL) {
		kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
				"no memory for tstream_writev_queue_send");
		return;
	}
	tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call);

	/*
	 * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
	 * packet_full_request_u32 provides the pdu length then.
	 */
	subreq = tstream_read_pdu_blob_send(kdc_conn,
					    kdc_conn->conn->event.ctx,
					    kdc_conn->tstream,
					    4, /* initial_read_size */
					    packet_full_request_u32,
					    kdc_conn);
	if (subreq == NULL) {
		kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
				"no memory for tstream_read_pdu_blob_send");
		return;
	}
	tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
}