summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/kdc/kdc-glue.h50
-rw-r--r--source4/kdc/kdc.c127
-rw-r--r--source4/kdc/proxy.c378
3 files changed, 303 insertions, 252 deletions
diff --git a/source4/kdc/kdc-glue.h b/source4/kdc/kdc-glue.h
index f9489b1fd1..b365cd75c6 100644
--- a/source4/kdc/kdc-glue.h
+++ b/source4/kdc/kdc-glue.h
@@ -50,46 +50,6 @@ enum kdc_process_ret {
KDC_PROCESS_FAILED,
KDC_PROCESS_PROXY};
-struct kdc_tcp_call {
- struct kdc_tcp_connection *kdc_conn;
- DATA_BLOB in;
- DATA_BLOB out;
- uint8_t out_hdr[4];
- struct iovec out_iov[2];
-};
-
-typedef enum kdc_process_ret (*kdc_process_fn_t)(struct kdc_server *kdc,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *input,
- DATA_BLOB *reply,
- struct tsocket_address *peer_addr,
- struct tsocket_address *my_addr,
- int datagram);
-
-
-/* hold information about one kdc socket */
-struct kdc_socket {
- struct kdc_server *kdc;
- struct tsocket_address *local_address;
- kdc_process_fn_t process;
-};
-
-/*
- state of an open tcp connection
-*/
-struct kdc_tcp_connection {
- /* stream connection we belong to */
- struct stream_connection *conn;
-
- /* the kdc_server the connection belongs to */
- struct kdc_socket *kdc_socket;
-
- struct tstream_context *tstream;
-
- struct tevent_queue *send_queue;
-};
-
-
enum kdc_process_ret kpasswdd_process(struct kdc_server *kdc,
TALLOC_CTX *mem_ctx,
DATA_BLOB *input,
@@ -112,7 +72,13 @@ NTSTATUS kdc_udp_proxy_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
DATA_BLOB *out);
-void kdc_tcp_proxy(struct kdc_server *kdc, struct kdc_tcp_connection *kdc_conn,
- struct kdc_tcp_call *call, uint16_t port);
+struct tevent_req *kdc_tcp_proxy_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct kdc_server *kdc,
+ uint16_t port,
+ DATA_BLOB in);
+NTSTATUS kdc_tcp_proxy_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ DATA_BLOB *out);
#endif
diff --git a/source4/kdc/kdc.c b/source4/kdc/kdc.c
index 05c1d9c40d..26365acc7c 100644
--- a/source4/kdc/kdc.c
+++ b/source4/kdc/kdc.c
@@ -62,6 +62,45 @@ static NTSTATUS kdc_proxy_unavailable_error(struct kdc_server *kdc,
return NT_STATUS_OK;
}
+typedef enum kdc_process_ret (*kdc_process_fn_t)(struct kdc_server *kdc,
+ TALLOC_CTX *mem_ctx,
+ DATA_BLOB *input,
+ DATA_BLOB *reply,
+ struct tsocket_address *peer_addr,
+ struct tsocket_address *my_addr,
+ int datagram);
+
+/* hold information about one kdc socket */
+struct kdc_socket {
+ struct kdc_server *kdc;
+ struct tsocket_address *local_address;
+ kdc_process_fn_t process;
+};
+
+struct kdc_tcp_call {
+ struct kdc_tcp_connection *kdc_conn;
+ DATA_BLOB in;
+ DATA_BLOB out;
+ uint8_t out_hdr[4];
+ struct iovec out_iov[2];
+};
+
+/*
+ state of an open tcp connection
+*/
+struct kdc_tcp_connection {
+ /* stream connection we belong to */
+ struct stream_connection *conn;
+
+ /* the kdc_server the connection belongs to */
+ struct kdc_socket *kdc_socket;
+
+ struct tstream_context *tstream;
+
+ struct tevent_queue *send_queue;
+};
+
+
static void kdc_tcp_terminate_connection(struct kdc_tcp_connection *kdcconn, const char *reason)
{
stream_terminate_connection(kdcconn->conn, reason);
@@ -143,6 +182,7 @@ static enum kdc_process_ret kdc_process(struct kdc_server *kdc,
return KDC_PROCESS_OK;
}
+static void kdc_tcp_call_proxy_done(struct tevent_req *subreq);
static void kdc_tcp_call_writev_done(struct tevent_req *subreq);
static void kdc_tcp_call_loop(struct tevent_req *subreq)
@@ -202,14 +242,94 @@ static void kdc_tcp_call_loop(struct tevent_req *subreq)
}
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;
}
- kdc_tcp_proxy(kdc_conn->kdc_socket->kdc, kdc_conn, call,
- tsocket_address_inet_port(kdc_conn->conn->local_address));
- goto done;
+ 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);
+}
+
+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 */
@@ -232,7 +352,6 @@ static void kdc_tcp_call_loop(struct tevent_req *subreq)
}
tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call);
-done:
/*
* The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
* packet_full_request_u32 provides the pdu length then.
diff --git a/source4/kdc/proxy.c b/source4/kdc/proxy.c
index a11f253b26..98db956f65 100644
--- a/source4/kdc/proxy.c
+++ b/source4/kdc/proxy.c
@@ -324,296 +324,262 @@ NTSTATUS kdc_udp_proxy_recv(struct tevent_req *req,
}
struct kdc_tcp_proxy_state {
- struct kdc_tcp_call *call;
- struct kdc_tcp_connection *kdc_conn;
+ struct tevent_context *ev;
struct kdc_server *kdc;
uint16_t port;
- uint32_t next_proxy;
+ DATA_BLOB in;
+ uint8_t in_hdr[4];
+ struct iovec in_iov[2];
+ DATA_BLOB out;
char **proxy_list;
- const char *proxy_ip;
+ uint32_t next_proxy;
+ struct {
+ struct nbt_name name;
+ const char *ip;
+ struct tstream_context *stream;
+ } proxy;
};
-static void kdc_tcp_next_proxy(struct kdc_tcp_proxy_state *state);
+static void kdc_tcp_next_proxy(struct tevent_req *req);
-/*
- called when the send of the proxied reply to the client is done
- */
-static void kdc_tcp_proxy_reply_done(struct tevent_req *req)
+struct tevent_req *kdc_tcp_proxy_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct kdc_server *kdc,
+ uint16_t port,
+ DATA_BLOB in)
{
- struct kdc_tcp_proxy_state *state = tevent_req_callback_data(req,
- struct kdc_tcp_proxy_state);
- int ret, sys_errno;
+ struct tevent_req *req;
+ struct kdc_tcp_proxy_state *state;
+ WERROR werr;
- ret = tstream_writev_queue_recv(req, &sys_errno);
- if (ret == -1) {
- DEBUG(4,("kdc_tcp_proxy: writev of reply gave %d : %s\n",
- sys_errno, strerror(sys_errno)));
+ req = tevent_req_create(mem_ctx, &state,
+ struct kdc_tcp_proxy_state);
+ if (req == NULL) {
+ return NULL;
}
- talloc_free(req);
- talloc_free(state);
-}
-
-/*
- called when the recv of the proxied reply is done
- */
-static void kdc_tcp_proxy_recv_done(struct tevent_req *req)
-{
- struct kdc_tcp_proxy_state *state = tevent_req_callback_data(req,
- struct kdc_tcp_proxy_state);
- NTSTATUS status;
-
- status = tstream_read_pdu_blob_recv(req,
- state,
- &state->call->out);
- talloc_free(req);
+ state->ev = ev;
+ state->kdc = kdc;
+ state->port = port;
+ state->in = in;
- if (!NT_STATUS_IS_OK(status)) {
- kdc_tcp_next_proxy(state);
- return;
+ werr = kdc_proxy_get_writeable_dcs(kdc, state, &state->proxy_list);
+ if (!W_ERROR_IS_OK(werr)) {
+ NTSTATUS status = werror_to_ntstatus(werr);
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
}
+ RSIVAL(state->in_hdr, 0, state->in.length);
+ state->in_iov[0].iov_base = (char *)state->in_hdr;
+ state->in_iov[0].iov_len = 4;
+ state->in_iov[1].iov_base = (char *)state->in.data;
+ state->in_iov[1].iov_len = state->in.length;
- /* send the reply to the original caller */
-
- state->call->out_iov[0].iov_base = (char *)state->call->out.data;
- state->call->out_iov[0].iov_len = state->call->out.length;
-
- req = tstream_writev_queue_send(state,
- state->kdc_conn->conn->event.ctx,
- state->kdc_conn->tstream,
- state->kdc_conn->send_queue,
- state->call->out_iov, 1);
- if (req == NULL) {
- kdc_tcp_next_proxy(state);
- return;
+ kdc_tcp_next_proxy(req);
+ if (!tevent_req_is_in_progress(req)) {
+ return tevent_req_post(req, ev);
}
- tevent_req_set_callback(req, kdc_tcp_proxy_reply_done, state);
+ return req;
}
-/*
- called when the send of the proxied packet is done
- */
-static void kdc_tcp_proxy_send_done(struct tevent_req *req)
-{
- struct kdc_tcp_proxy_state *state = tevent_req_callback_data(req,
- struct kdc_tcp_proxy_state);
- int ret, sys_errno;
-
- ret = tstream_writev_queue_recv(req, &sys_errno);
- talloc_free(req);
- if (ret == -1) {
- kdc_tcp_next_proxy(state);
- }
-}
+static void kdc_tcp_proxy_resolve_done(struct composite_context *csubreq);
/*
- called when we've connected to the proxy
+ try the next proxy in the list
*/
-static void kdc_tcp_proxy_connect_done(struct tevent_req *req)
+static void kdc_tcp_next_proxy(struct tevent_req *req)
{
- struct kdc_tcp_proxy_state *state = tevent_req_callback_data(req,
- struct kdc_tcp_proxy_state);
- int ret, sys_errno;
- struct tstream_context *stream;
- struct tevent_queue *send_queue;
-
-
- ret = tstream_inet_tcp_connect_recv(req, &sys_errno, state, &stream, NULL);
- talloc_free(req);
+ struct kdc_tcp_proxy_state *state =
+ tevent_req_data(req,
+ struct kdc_tcp_proxy_state);
+ const char *proxy_dnsname = state->proxy_list[state->next_proxy];
+ struct composite_context *csubreq;
- if (ret != 0) {
- kdc_tcp_next_proxy(state);
+ if (proxy_dnsname == NULL) {
+ tevent_req_nterror(req, NT_STATUS_NO_LOGON_SERVERS);
return;
}
- RSIVAL(state->call->out_hdr, 0, state->call->in.length);
- state->call->out_iov[0].iov_base = (char *)state->call->out_hdr;
- state->call->out_iov[0].iov_len = 4;
- state->call->out_iov[1].iov_base = (char *) state->call->in.data;
- state->call->out_iov[1].iov_len = state->call->in.length;
-
- send_queue = tevent_queue_create(state, "kdc_tcp_proxy");
- if (send_queue == NULL) {
- kdc_tcp_next_proxy(state);
- return;
- }
+ state->next_proxy++;
- req = tstream_writev_queue_send(state,
- state->kdc_conn->conn->event.ctx,
- stream,
- send_queue,
- state->call->out_iov, 2);
- if (req == NULL) {
- kdc_tcp_next_proxy(state);
- return;
- }
+ /* make sure we close the socket of the last try */
+ TALLOC_FREE(state->proxy.stream);
+ ZERO_STRUCT(state->proxy);
- tevent_req_set_callback(req, kdc_tcp_proxy_send_done, state);
+ make_nbt_name(&state->proxy.name, proxy_dnsname, 0);
- req = tstream_read_pdu_blob_send(state,
- state->kdc_conn->conn->event.ctx,
- stream,
- 4, /* initial_read_size */
- packet_full_request_u32,
- state);
- if (req == NULL) {
- kdc_tcp_next_proxy(state);
+ csubreq = resolve_name_ex_send(lpcfg_resolve_context(state->kdc->task->lp_ctx),
+ state,
+ RESOLVE_NAME_FLAG_FORCE_DNS,
+ 0,
+ &state->proxy.name,
+ state->ev);
+ if (tevent_req_nomem(csubreq, req)) {
return;
}
-
- tevent_req_set_callback(req, kdc_tcp_proxy_recv_done, state);
- tevent_req_set_endtime(req, state->kdc->task->event_ctx,
- timeval_current_ofs(state->kdc->proxy_timeout, 0));
-
+ csubreq->async.fn = kdc_tcp_proxy_resolve_done;
+ csubreq->async.private_data = req;
}
+static void kdc_tcp_proxy_connect_done(struct tevent_req *subreq);
-/*
- called when name resolution for a proxy is done
- */
-static void kdc_tcp_proxy_resolve_done(struct composite_context *c)
+static void kdc_tcp_proxy_resolve_done(struct composite_context *csubreq)
{
- struct kdc_tcp_proxy_state *state;
+ struct tevent_req *req =
+ talloc_get_type_abort(csubreq->async.private_data,
+ struct tevent_req);
+ struct kdc_tcp_proxy_state *state =
+ tevent_req_data(req,
+ struct kdc_tcp_proxy_state);
NTSTATUS status;
- struct tevent_req *req;
+ struct tevent_req *subreq;
struct tsocket_address *local_addr, *proxy_addr;
int ret;
- state = talloc_get_type(c->async.private_data, struct kdc_tcp_proxy_state);
-
- status = resolve_name_recv(c, state, &state->proxy_ip);
+ status = resolve_name_recv(csubreq, state, &state->proxy.ip);
if (!NT_STATUS_IS_OK(status)) {
- kdc_tcp_next_proxy(state);
+ DEBUG(0,("Unable to resolve proxy[%s] - %s\n",
+ state->proxy.name.name, nt_errstr(status)));
+ kdc_tcp_next_proxy(req);
return;
}
/* get an address for us to use locally */
ret = tsocket_address_inet_from_strings(state, "ip", NULL, 0, &local_addr);
if (ret != 0) {
- kdc_tcp_next_proxy(state);
+ kdc_tcp_next_proxy(req);
return;
}
ret = tsocket_address_inet_from_strings(state, "ip",
- state->proxy_ip, state->port, &proxy_addr);
+ state->proxy.ip,
+ state->port,
+ &proxy_addr);
if (ret != 0) {
- kdc_tcp_next_proxy(state);
+ kdc_tcp_next_proxy(req);
return;
}
- /* connect to the proxy */
- req = tstream_inet_tcp_connect_send(state, state->kdc->task->event_ctx, local_addr, proxy_addr);
- if (req == NULL) {
- kdc_tcp_next_proxy(state);
+ subreq = tstream_inet_tcp_connect_send(state, state->ev,
+ local_addr, proxy_addr);
+ if (tevent_req_nomem(subreq, req)) {
return;
}
-
- tevent_req_set_callback(req, kdc_tcp_proxy_connect_done, state);
-
- tevent_req_set_endtime(req, state->kdc->task->event_ctx,
+ tevent_req_set_callback(subreq, kdc_tcp_proxy_connect_done, req);
+ tevent_req_set_endtime(subreq, state->ev,
timeval_current_ofs(state->kdc->proxy_timeout, 0));
-
- DEBUG(4,("kdc_tcp_proxy: proxying request to %s\n", state->proxy_ip));
}
+static void kdc_tcp_proxy_writev_done(struct tevent_req *subreq);
+static void kdc_tcp_proxy_read_pdu_done(struct tevent_req *subreq);
-/*
- called when our proxies are not available
- */
-static void kdc_tcp_proxy_unavailable(struct kdc_tcp_proxy_state *state)
+static void kdc_tcp_proxy_connect_done(struct tevent_req *subreq)
{
- int kret;
- krb5_data k5_error_blob;
- struct tevent_req *req;
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct kdc_tcp_proxy_state *state =
+ tevent_req_data(req,
+ struct kdc_tcp_proxy_state);
+ int ret, sys_errno;
- kret = krb5_mk_error(state->kdc->smb_krb5_context->krb5_context,
- KRB5KDC_ERR_SVC_UNAVAILABLE, NULL, NULL,
- NULL, NULL, NULL, NULL, &k5_error_blob);
- if (kret != 0) {
- DEBUG(2,(__location__ ": Unable to form krb5 error reply\n"));
- talloc_free(state);
+ ret = tstream_inet_tcp_connect_recv(subreq, &sys_errno,
+ state, &state->proxy.stream, NULL);
+ TALLOC_FREE(subreq);
+ if (ret != 0) {
+ kdc_tcp_next_proxy(req);
return;
}
-
- state->call->out = data_blob_talloc(state, k5_error_blob.data, k5_error_blob.length);
- krb5_data_free(&k5_error_blob);
- if (!state->call->out.data) {
- talloc_free(state);
+ subreq = tstream_writev_send(state,
+ state->ev,
+ state->proxy.stream,
+ state->in_iov, 2);
+ if (tevent_req_nomem(subreq, req)) {
return;
}
+ tevent_req_set_callback(subreq, kdc_tcp_proxy_writev_done, req);
- state->call->out_iov[0].iov_base = (char *)state->call->out.data;
- state->call->out_iov[0].iov_len = state->call->out.length;
-
- req = tstream_writev_queue_send(state,
- state->kdc_conn->conn->event.ctx,
- state->kdc_conn->tstream,
- state->kdc_conn->send_queue,
- state->call->out_iov, 1);
- if (!req) {
- talloc_free(state);
+ subreq = tstream_read_pdu_blob_send(state,
+ state->ev,
+ state->proxy.stream,
+ 4, /* initial_read_size */
+ packet_full_request_u32,
+ req);
+ if (tevent_req_nomem(subreq, req)) {
return;
}
+ tevent_req_set_callback(subreq, kdc_tcp_proxy_read_pdu_done, req);
+ tevent_req_set_endtime(subreq, state->kdc->task->event_ctx,
+ timeval_current_ofs(state->kdc->proxy_timeout, 0));
- tevent_req_set_callback(req, kdc_tcp_proxy_reply_done, state);
+ DEBUG(4,("kdc_tcp_proxy: proxying request to %s[%s]\n",
+ state->proxy.name.name, state->proxy.ip));
}
-/*
- try the next proxy in the list
- */
-static void kdc_tcp_next_proxy(struct kdc_tcp_proxy_state *state)
+static void kdc_tcp_proxy_writev_done(struct tevent_req *subreq)
{
- const char *proxy_dnsname = state->proxy_list[state->next_proxy];
- struct nbt_name name;
- struct composite_context *c;
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret, sys_errno;
- if (proxy_dnsname == NULL) {
- kdc_tcp_proxy_unavailable(state);
- return;
+ ret = tstream_writev_recv(subreq, &sys_errno);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ kdc_tcp_next_proxy(req);
}
+}
- state->next_proxy++;
+static void kdc_tcp_proxy_read_pdu_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct kdc_tcp_proxy_state *state =
+ tevent_req_data(req,
+ struct kdc_tcp_proxy_state);
+ NTSTATUS status;
+ DATA_BLOB raw;
- make_nbt_name(&name, proxy_dnsname, 0);
+ status = tstream_read_pdu_blob_recv(subreq, state, &raw);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ kdc_tcp_next_proxy(req);
+ return;
+ }
- c = resolve_name_ex_send(lpcfg_resolve_context(state->kdc->task->lp_ctx),
- state,
- RESOLVE_NAME_FLAG_FORCE_DNS,
- 0,
- &name,
- state->kdc->task->event_ctx);
- if (c == NULL) {
- kdc_tcp_next_proxy(state);
+ /*
+ * raw blob has the length in the first 4 bytes,
+ * which we do not need here.
+ */
+ state->out = data_blob_talloc(state, raw.data + 4, raw.length - 4);
+ if (state->out.length != raw.length - 4) {
+ tevent_req_nomem(NULL, req);
return;
}
- c->async.fn = kdc_tcp_proxy_resolve_done;
- c->async.private_data = state;
-}
+ tevent_req_done(req);
+}
-/*
- proxy a TCP kdc request to a writeable DC
- */
-void kdc_tcp_proxy(struct kdc_server *kdc, struct kdc_tcp_connection *kdc_conn,
- struct kdc_tcp_call *call, uint16_t port)
+NTSTATUS kdc_tcp_proxy_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ DATA_BLOB *out)
{
- struct kdc_tcp_proxy_state *state;
- WERROR werr;
-
- state = talloc_zero(kdc_conn, struct kdc_tcp_proxy_state);
-
- state->call = talloc_steal(state, call);
- state->kdc_conn = kdc_conn;
- state->kdc = kdc;
- state->port = port;
+ struct kdc_tcp_proxy_state *state =
+ tevent_req_data(req,
+ struct kdc_tcp_proxy_state);
+ NTSTATUS status;
- werr = kdc_proxy_get_writeable_dcs(kdc, state, &state->proxy_list);
- if (!W_ERROR_IS_OK(werr)) {
- kdc_tcp_proxy_unavailable(state);
- return;
+ if (tevent_req_is_nterror(req, &status)) {
+ tevent_req_received(req);
+ return status;
}
- kdc_tcp_next_proxy(state);
+ out->data = talloc_move(mem_ctx, &state->out.data);
+ out->length = state->out.length;
+
+ tevent_req_received(req);
+ return NT_STATUS_OK;
}