Exemple #1
0
static bool ldapsrv_call_read_next(struct ldapsrv_connection *conn)
{
	struct tevent_req *subreq;

	if (timeval_is_zero(&conn->limits.endtime)) {
		conn->limits.endtime =
			timeval_current_ofs(conn->limits.initial_timeout, 0);
	} else {
		conn->limits.endtime =
			timeval_current_ofs(conn->limits.conn_idle_time, 0);
	}

	/*
	 * The minimun size of a LDAP pdu is 7 bytes
	 *
	 * dumpasn1 -hh ldap-unbind-min.dat
	 *
	 *     <30 05 02 01 09 42 00>
	 *    0    5: SEQUENCE {
	 *     <02 01 09>
	 *    2    1:   INTEGER 9
	 *     <42 00>
	 *    5    0:   [APPLICATION 2]
	 *          :     Error: Object has zero length.
	 *          :   }
	 *
	 * dumpasn1 -hh ldap-unbind-windows.dat
	 *
	 *     <30 84 00 00 00 05 02 01 09 42 00>
	 *    0    5: SEQUENCE {
	 *     <02 01 09>
	 *    6    1:   INTEGER 9
	 *     <42 00>
	 *    9    0:   [APPLICATION 2]
	 *          :     Error: Object has zero length.
	 *          :   }
	 *
	 * This means using an initial read size
	 * of 7 is ok.
	 */
	subreq = tstream_read_pdu_blob_send(conn,
					    conn->connection->event.ctx,
					    conn->sockets.active,
					    7, /* initial_read_size */
					    ldap_full_packet,
					    conn);
	if (subreq == NULL) {
		ldapsrv_terminate_connection(conn, "ldapsrv_call_read_next: "
				"no memory for tstream_read_pdu_blob_send");
		return false;
	}
	tevent_req_set_endtime(subreq,
			       conn->connection->event.ctx,
			       conn->limits.endtime);
	tevent_req_set_callback(subreq, ldapsrv_call_read_done, conn);
	return true;
}
Exemple #2
0
/*
  called when we get a new connection
*/
static void kdc_tcp_accept(struct stream_connection *conn)
{
	struct kdc_socket *kdc_socket;
	struct kdc_tcp_connection *kdc_conn;
	struct tevent_req *subreq;
	int rc;

	kdc_conn = talloc_zero(conn, struct kdc_tcp_connection);
	if (kdc_conn == NULL) {
		stream_terminate_connection(conn,
				"kdc_tcp_accept: out of memory");
		return;
	}

	kdc_conn->send_queue = tevent_queue_create(conn, "kdc_tcp_accept");
	if (kdc_conn->send_queue == NULL) {
		stream_terminate_connection(conn,
				"kdc_tcp_accept: out of memory");
		return;
	}

	kdc_socket = talloc_get_type(conn->private_data, struct kdc_socket);

	TALLOC_FREE(conn->event.fde);

	rc = tstream_bsd_existing_socket(kdc_conn,
			socket_get_fd(conn->socket),
			&kdc_conn->tstream);
	if (rc < 0) {
		stream_terminate_connection(conn,
				"kdc_tcp_accept: out of memory");
		return;
	}

	kdc_conn->conn = conn;
	kdc_conn->kdc_socket = kdc_socket;
	conn->private_data = kdc_conn;

	/*
	 * 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_accept: "
				"no memory for tstream_read_pdu_blob_send");
		return;
	}
	tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
}
Exemple #3
0
static void wbsrv_accept(struct stream_connection *conn)
{
	struct wbsrv_listen_socket *wbsrv_socket = talloc_get_type(conn->private_data,
								   struct wbsrv_listen_socket);
	struct wbsrv_connection *wbsrv_conn;
	struct tevent_req *subreq;
	int rc;

	wbsrv_conn = talloc_zero(conn, struct wbsrv_connection);
	if (wbsrv_conn == NULL) {
		stream_terminate_connection(conn, "wbsrv_accept: out of memory");
		return;
	}

	wbsrv_conn->send_queue = tevent_queue_create(conn, "wbsrv_accept");
	if (wbsrv_conn->send_queue == NULL) {
		stream_terminate_connection(conn,
				"wbsrv_accept: out of memory");
		return;
	}

	TALLOC_FREE(conn->event.fde);

	rc = tstream_bsd_existing_socket(wbsrv_conn,
			socket_get_fd(conn->socket),
			&wbsrv_conn->tstream);
	if (rc < 0) {
		stream_terminate_connection(conn,
				"wbsrv_accept: out of memory");
		return;
	}

	wbsrv_conn->conn = conn;
	wbsrv_conn->listen_socket = wbsrv_socket;
	wbsrv_conn->lp_ctx = wbsrv_socket->service->task->lp_ctx;
	conn->private_data = wbsrv_conn;

	/*
	 * 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_accept: "
				"no memory for tstream_read_pdu_blob_send");
		return;
	}
	tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn);
}
Exemple #4
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);
}
/*
  called when we get a new connection
*/
static void wreplsrv_accept(struct stream_connection *conn)
{
	struct wreplsrv_service *service = talloc_get_type(conn->private_data, struct wreplsrv_service);
	struct wreplsrv_in_connection *wrepl_conn;
	struct tsocket_address *peer_addr;
	char *peer_ip;
	struct tevent_req *subreq;
	int rc;

	wrepl_conn = talloc_zero(conn, struct wreplsrv_in_connection);
	if (wrepl_conn == NULL) {
		stream_terminate_connection(conn,
					    "wreplsrv_accept: out of memory");
		return;
	}

	wrepl_conn->send_queue = tevent_queue_create(conn, "wrepl_accept");
	if (wrepl_conn->send_queue == NULL) {
		stream_terminate_connection(conn,
					    "wrepl_accept: out of memory");
		return;
	}

	TALLOC_FREE(conn->event.fde);

	rc = tstream_bsd_existing_socket(wrepl_conn,
					 socket_get_fd(conn->socket),
					 &wrepl_conn->tstream);
	if (rc < 0) {
		stream_terminate_connection(conn,
					    "wrepl_accept: out of memory");
		return;
	}
	socket_set_flags(conn->socket, SOCKET_FLAG_NOCLOSE);

	wrepl_conn->conn = conn;
	wrepl_conn->service = service;

	peer_addr = conn->remote_address;

	if (!tsocket_address_is_inet(peer_addr, "ipv4")) {
		DEBUG(0,("wreplsrv_accept: non ipv4 peer addr '%s'\n",
			tsocket_address_string(peer_addr, wrepl_conn)));
		wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_accept: "
				"invalid peer IP");
		return;
	}

	peer_ip = tsocket_address_inet_addr_string(peer_addr, wrepl_conn);
	if (peer_ip == NULL) {
		wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_accept: "
				"could not convert peer IP into a string");
		return;
	}

	wrepl_conn->partner = wreplsrv_find_partner(service, peer_ip);
	irpc_add_name(conn->msg_ctx, "wreplsrv_connection");

	/*
	 * The wrepl 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(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, "wrepl_accept: "
				"no memory for tstream_read_pdu_blob_send");
		return;
	}
	tevent_req_set_callback(subreq, wreplsrv_call_loop, wrepl_conn);
}
/*
  called when we get a new connection
*/
NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner,
				      uint32_t peer_assoc_ctx,
				      struct tstream_context **stream,
				      struct wreplsrv_in_connection **_wrepl_in)
{
	struct wreplsrv_service *service = partner->service;
	struct wreplsrv_in_connection *wrepl_in;
	const struct model_ops *model_ops;
	struct stream_connection *conn;
	struct tevent_req *subreq;
	NTSTATUS status;

	/* within the wrepl task we want to be a single process, so
	   ask for the single process model ops and pass these to the
	   stream_setup_socket() call. */
	model_ops = process_model_startup("single");
	if (!model_ops) {
		DEBUG(0,("Can't find 'single' process model_ops"));
		return NT_STATUS_INTERNAL_ERROR;
	}

	wrepl_in = talloc_zero(partner, struct wreplsrv_in_connection);
	NT_STATUS_HAVE_NO_MEMORY(wrepl_in);

	wrepl_in->service	= service;
	wrepl_in->partner	= partner;
	wrepl_in->tstream	= talloc_move(wrepl_in, stream);
	wrepl_in->assoc_ctx.peer_ctx = peer_assoc_ctx;

	status = stream_new_connection_merge(service->task->event_ctx,
					     service->task->lp_ctx,
					     model_ops,
					     &wreplsrv_stream_ops,
					     service->task->msg_ctx,
					     wrepl_in,
					     &conn);
	NT_STATUS_NOT_OK_RETURN(status);

	/*
	 * make the wreplsrv_in_connection structure a child of the
	 * stream_connection, to match the hierarchy of wreplsrv_accept
	 */
	wrepl_in->conn		= conn;
	talloc_steal(conn, wrepl_in);

	wrepl_in->send_queue = tevent_queue_create(wrepl_in, "wreplsrv_in_connection_merge");
	if (wrepl_in->send_queue == NULL) {
		stream_terminate_connection(conn,
					    "wreplsrv_in_connection_merge: out of memory");
		return NT_STATUS_NO_MEMORY;
	}

	/*
	 * The wrepl 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(wrepl_in,
					    wrepl_in->conn->event.ctx,
					    wrepl_in->tstream,
					    4, /* initial_read_size */
					    packet_full_request_u32,
					    wrepl_in);
	if (subreq == NULL) {
		wreplsrv_terminate_in_connection(wrepl_in, "wreplsrv_in_connection_merge: "
				"no memory for tstream_read_pdu_blob_send");
		return NT_STATUS_NO_MEMORY;
	}
	tevent_req_set_callback(subreq, wreplsrv_call_loop, wrepl_in);

	*_wrepl_in = wrepl_in;

	return NT_STATUS_OK;
}
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);
}
Exemple #8
0
static void kdc_tcp_call_proxy_done(struct tevent_req *subreq)
{
	struct kdc_tcp_call *call = tevent_req_callback_data(subreq,
			struct kdc_tcp_call);
	struct kdc_tcp_connection *kdc_conn = call->kdc_conn;
	NTSTATUS status;

	status = kdc_tcp_proxy_recv(subreq, call, &call->out);
	TALLOC_FREE(subreq);
	if (!NT_STATUS_IS_OK(status)) {
		/* generate an error packet */
		status = kdc_proxy_unavailable_error(kdc_conn->kdc_socket->kdc,
						     call, &call->out);
	}

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

		reason = talloc_asprintf(call, "kdc_tcp_call_proxy_done: "
					 "kdc_proxy_unavailable_error - %s",
					 nt_errstr(status));
		if (!reason) {
			reason = "kdc_tcp_call_proxy_done: kdc_proxy_unavailable_error() failed";
		}

		kdc_tcp_terminate_connection(call->kdc_conn, reason);
		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);
}
Exemple #9
0
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);
}