mirror of
https://github.com/samba-team/samba.git
synced 2025-03-27 22:50:26 +03:00
s4:kdc: split the kdc_udp_proxy() logic from the main kdc logic
By having kdc_udp_proxy_send/recv(), which just asks any writeable dc for a reponse blob, we simplify the interaction between client-local and local-writeable sockets. This allows us to make kdc_udp_call and kdc_udp_socket private to kdc.c again. metze
This commit is contained in:
parent
ad9ac99afd
commit
e70b09e8f8
@ -50,19 +50,6 @@ enum kdc_process_ret {
|
||||
KDC_PROCESS_FAILED,
|
||||
KDC_PROCESS_PROXY};
|
||||
|
||||
struct kdc_udp_call {
|
||||
struct tsocket_address *src;
|
||||
DATA_BLOB in;
|
||||
DATA_BLOB out;
|
||||
};
|
||||
|
||||
/* hold information about one kdc/kpasswd udp socket */
|
||||
struct kdc_udp_socket {
|
||||
struct kdc_socket *kdc_socket;
|
||||
struct tdgram_context *dgram;
|
||||
struct tevent_queue *send_queue;
|
||||
};
|
||||
|
||||
struct kdc_tcp_call {
|
||||
struct kdc_tcp_connection *kdc_conn;
|
||||
DATA_BLOB in;
|
||||
@ -116,8 +103,14 @@ NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx,
|
||||
krb5_context context, struct HDB **db);
|
||||
|
||||
/* from proxy.c */
|
||||
void kdc_udp_proxy(struct kdc_server *kdc, struct kdc_udp_socket *sock,
|
||||
struct kdc_udp_call *call, uint16_t port);
|
||||
struct tevent_req *kdc_udp_proxy_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct kdc_server *kdc,
|
||||
uint16_t port,
|
||||
DATA_BLOB in);
|
||||
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);
|
||||
|
@ -345,6 +345,21 @@ static const struct stream_server_ops kdc_tcp_stream_ops = {
|
||||
.send_handler = kdc_tcp_send
|
||||
};
|
||||
|
||||
/* hold information about one kdc/kpasswd udp socket */
|
||||
struct kdc_udp_socket {
|
||||
struct kdc_socket *kdc_socket;
|
||||
struct tdgram_context *dgram;
|
||||
struct tevent_queue *send_queue;
|
||||
};
|
||||
|
||||
struct kdc_udp_call {
|
||||
struct kdc_udp_socket *sock;
|
||||
struct tsocket_address *src;
|
||||
DATA_BLOB in;
|
||||
DATA_BLOB out;
|
||||
};
|
||||
|
||||
static void kdc_udp_call_proxy_done(struct tevent_req *subreq);
|
||||
static void kdc_udp_call_sendto_done(struct tevent_req *subreq);
|
||||
|
||||
static void kdc_udp_call_loop(struct tevent_req *subreq)
|
||||
@ -362,6 +377,7 @@ static void kdc_udp_call_loop(struct tevent_req *subreq)
|
||||
talloc_free(call);
|
||||
goto done;
|
||||
}
|
||||
call->sock = sock;
|
||||
|
||||
len = tdgram_recvfrom_recv(subreq, &sys_errno,
|
||||
call, &buf, &call->src);
|
||||
@ -392,13 +408,26 @@ static void kdc_udp_call_loop(struct tevent_req *subreq)
|
||||
}
|
||||
|
||||
if (ret == KDC_PROCESS_PROXY) {
|
||||
uint16_t port;
|
||||
|
||||
if (!sock->kdc_socket->kdc->am_rodc) {
|
||||
DEBUG(0,("kdc_udp_call_loop: proxying requested when not RODC"));
|
||||
talloc_free(call);
|
||||
goto done;
|
||||
}
|
||||
kdc_udp_proxy(sock->kdc_socket->kdc, sock, call,
|
||||
tsocket_address_inet_port(sock->kdc_socket->local_address));
|
||||
|
||||
port = tsocket_address_inet_port(sock->kdc_socket->local_address);
|
||||
|
||||
subreq = kdc_udp_proxy_send(call,
|
||||
sock->kdc_socket->kdc->task->event_ctx,
|
||||
sock->kdc_socket->kdc,
|
||||
port,
|
||||
call->in);
|
||||
if (subreq == NULL) {
|
||||
talloc_free(call);
|
||||
goto done;
|
||||
}
|
||||
tevent_req_set_callback(subreq, kdc_udp_call_proxy_done, call);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -428,6 +457,41 @@ done:
|
||||
tevent_req_set_callback(subreq, kdc_udp_call_loop, sock);
|
||||
}
|
||||
|
||||
static void kdc_udp_call_proxy_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct kdc_udp_call *call =
|
||||
tevent_req_callback_data(subreq,
|
||||
struct kdc_udp_call);
|
||||
NTSTATUS status;
|
||||
|
||||
status = kdc_udp_proxy_recv(subreq, call, &call->out);
|
||||
TALLOC_FREE(subreq);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
/* generate an error packet */
|
||||
status = kdc_proxy_unavailable_error(call->sock->kdc_socket->kdc,
|
||||
call, &call->out);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(call);
|
||||
return;
|
||||
}
|
||||
|
||||
subreq = tdgram_sendto_queue_send(call,
|
||||
call->sock->kdc_socket->kdc->task->event_ctx,
|
||||
call->sock->dgram,
|
||||
call->sock->send_queue,
|
||||
call->out.data,
|
||||
call->out.length,
|
||||
call->src);
|
||||
if (subreq == NULL) {
|
||||
talloc_free(call);
|
||||
return;
|
||||
}
|
||||
|
||||
tevent_req_set_callback(subreq, kdc_udp_call_sendto_done, call);
|
||||
}
|
||||
|
||||
static void kdc_udp_call_sendto_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct kdc_udp_call *call = tevent_req_callback_data(subreq,
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
Copyright (C) Andrew Tridgell 2010
|
||||
Copyright (C) Andrew Bartlett 2010
|
||||
Copyright (C) Stefan Metzmacher 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -24,6 +25,7 @@
|
||||
#include "smbd/process_model.h"
|
||||
#include "lib/tsocket/tsocket.h"
|
||||
#include "libcli/util/tstream.h"
|
||||
#include "lib/util/tevent_ntstatus.h"
|
||||
#include "lib/stream/packet.h"
|
||||
#include "kdc/kdc-glue.h"
|
||||
#include "dsdb/samdb/samdb.h"
|
||||
@ -75,286 +77,251 @@ static WERROR kdc_proxy_get_writeable_dcs(struct kdc_server *kdc, TALLOC_CTX *me
|
||||
|
||||
|
||||
struct kdc_udp_proxy_state {
|
||||
struct kdc_udp_call *call;
|
||||
struct kdc_udp_socket *sock;
|
||||
struct tevent_context *ev;
|
||||
struct kdc_server *kdc;
|
||||
uint16_t port;
|
||||
DATA_BLOB in;
|
||||
DATA_BLOB out;
|
||||
char **proxy_list;
|
||||
uint32_t next_proxy;
|
||||
const char *proxy_ip;
|
||||
uint16_t port;
|
||||
struct {
|
||||
struct nbt_name name;
|
||||
const char *ip;
|
||||
struct tdgram_context *dgram;
|
||||
} proxy;
|
||||
};
|
||||
|
||||
|
||||
static void kdc_udp_next_proxy(struct kdc_udp_proxy_state *state);
|
||||
static void kdc_udp_next_proxy(struct tevent_req *req);
|
||||
|
||||
/*
|
||||
called when the send of the call to the proxy is complete
|
||||
this is used to get an errors from the sendto()
|
||||
*/
|
||||
static void kdc_udp_proxy_sendto_done(struct tevent_req *req)
|
||||
struct tevent_req *kdc_udp_proxy_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct kdc_server *kdc,
|
||||
uint16_t port,
|
||||
DATA_BLOB in)
|
||||
{
|
||||
struct kdc_udp_proxy_state *state = tevent_req_callback_data(req,
|
||||
struct kdc_udp_proxy_state);
|
||||
ssize_t ret;
|
||||
int sys_errno;
|
||||
|
||||
ret = tdgram_sendto_queue_recv(req, &sys_errno);
|
||||
talloc_free(req);
|
||||
|
||||
if (ret == -1) {
|
||||
DEBUG(4,("kdc_udp_proxy: sendto for %s gave %d : %s\n",
|
||||
state->proxy_ip, sys_errno, strerror(sys_errno)));
|
||||
kdc_udp_next_proxy(state);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
called when the send of the reply to the client is complete
|
||||
this is used to get an errors from the sendto()
|
||||
*/
|
||||
static void kdc_udp_proxy_reply_done(struct tevent_req *req)
|
||||
{
|
||||
struct kdc_udp_proxy_state *state = tevent_req_callback_data(req,
|
||||
struct kdc_udp_proxy_state);
|
||||
ssize_t ret;
|
||||
int sys_errno;
|
||||
|
||||
ret = tdgram_sendto_queue_recv(req, &sys_errno);
|
||||
if (ret == -1) {
|
||||
DEBUG(3,("kdc_udp_proxy: reply sendto gave %d : %s\n",
|
||||
sys_errno, strerror(sys_errno)));
|
||||
}
|
||||
|
||||
/* all done - we can destroy the proxy state */
|
||||
talloc_free(req);
|
||||
talloc_free(state);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
called when the proxy replies
|
||||
*/
|
||||
static void kdc_udp_proxy_reply(struct tevent_req *req)
|
||||
{
|
||||
struct kdc_udp_proxy_state *state = tevent_req_callback_data(req,
|
||||
struct kdc_udp_proxy_state);
|
||||
int sys_errno;
|
||||
uint8_t *buf;
|
||||
struct tsocket_address *src;
|
||||
ssize_t len;
|
||||
|
||||
len = tdgram_recvfrom_recv(req, &sys_errno,
|
||||
state, &buf, &src);
|
||||
talloc_free(req);
|
||||
if (len == -1) {
|
||||
DEBUG(4,("kdc_udp_proxy: reply from %s gave %d : %s\n",
|
||||
state->proxy_ip, sys_errno, strerror(sys_errno)));
|
||||
kdc_udp_next_proxy(state);
|
||||
return;
|
||||
}
|
||||
|
||||
state->call->out.length = len;
|
||||
state->call->out.data = buf;
|
||||
|
||||
/* TODO: check the reply came from the right IP? */
|
||||
|
||||
req = tdgram_sendto_queue_send(state,
|
||||
state->kdc->task->event_ctx,
|
||||
state->sock->dgram,
|
||||
state->sock->send_queue,
|
||||
state->call->out.data,
|
||||
state->call->out.length,
|
||||
state->call->src);
|
||||
if (req == NULL) {
|
||||
kdc_udp_next_proxy(state);
|
||||
return;
|
||||
}
|
||||
|
||||
tevent_req_set_callback(req, kdc_udp_proxy_reply_done, state);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
called when we've resolved the name of a proxy
|
||||
*/
|
||||
static void kdc_udp_proxy_resolve_done(struct composite_context *c)
|
||||
{
|
||||
struct kdc_udp_proxy_state *state;
|
||||
NTSTATUS status;
|
||||
struct tevent_req *req;
|
||||
struct kdc_udp_proxy_state *state;
|
||||
WERROR werr;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state,
|
||||
struct kdc_udp_proxy_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
state->ev = ev;
|
||||
state->kdc = kdc;
|
||||
state->port = port;
|
||||
state->in = in;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
kdc_udp_next_proxy(req);
|
||||
if (!tevent_req_is_in_progress(req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
static void kdc_udp_proxy_resolve_done(struct composite_context *csubreq);
|
||||
|
||||
/*
|
||||
try the next proxy in the list
|
||||
*/
|
||||
static void kdc_udp_next_proxy(struct tevent_req *req)
|
||||
{
|
||||
struct kdc_udp_proxy_state *state =
|
||||
tevent_req_data(req,
|
||||
struct kdc_udp_proxy_state);
|
||||
const char *proxy_dnsname = state->proxy_list[state->next_proxy];
|
||||
struct composite_context *csubreq;
|
||||
|
||||
if (proxy_dnsname == NULL) {
|
||||
tevent_req_nterror(req, NT_STATUS_NO_LOGON_SERVERS);
|
||||
return;
|
||||
}
|
||||
|
||||
state->next_proxy++;
|
||||
|
||||
/* make sure we close the socket of the last try */
|
||||
TALLOC_FREE(state->proxy.dgram);
|
||||
ZERO_STRUCT(state->proxy);
|
||||
|
||||
make_nbt_name(&state->proxy.name, proxy_dnsname, 0);
|
||||
|
||||
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;
|
||||
}
|
||||
csubreq->async.fn = kdc_udp_proxy_resolve_done;
|
||||
csubreq->async.private_data = req;
|
||||
}
|
||||
|
||||
static void kdc_udp_proxy_sendto_done(struct tevent_req *subreq);
|
||||
static void kdc_udp_proxy_recvfrom_done(struct tevent_req *subreq);
|
||||
|
||||
static void kdc_udp_proxy_resolve_done(struct composite_context *csubreq)
|
||||
{
|
||||
struct tevent_req *req =
|
||||
talloc_get_type_abort(csubreq->async.private_data,
|
||||
struct tevent_req);
|
||||
struct kdc_udp_proxy_state *state =
|
||||
tevent_req_data(req,
|
||||
struct kdc_udp_proxy_state);
|
||||
NTSTATUS status;
|
||||
struct tevent_req *subreq;
|
||||
struct tsocket_address *local_addr, *proxy_addr;
|
||||
int ret;
|
||||
struct tdgram_context *dgram;
|
||||
struct tevent_queue *send_queue;
|
||||
|
||||
state = talloc_get_type(c->async.private_data, struct kdc_udp_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)) {
|
||||
DEBUG(0,("Unable to resolve proxy\n"));
|
||||
kdc_udp_next_proxy(state);
|
||||
DEBUG(0,("Unable to resolve proxy[%s] - %s\n",
|
||||
state->proxy.name.name, nt_errstr(status)));
|
||||
kdc_udp_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_udp_next_proxy(state);
|
||||
kdc_udp_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_udp_next_proxy(state);
|
||||
kdc_udp_next_proxy(req);
|
||||
return;
|
||||
}
|
||||
|
||||
/* create a socket for us to work on */
|
||||
ret = tdgram_inet_udp_socket(local_addr, proxy_addr, state, &dgram);
|
||||
ret = tdgram_inet_udp_socket(local_addr, proxy_addr,
|
||||
state, &state->proxy.dgram);
|
||||
if (ret != 0) {
|
||||
kdc_udp_next_proxy(state);
|
||||
kdc_udp_next_proxy(req);
|
||||
return;
|
||||
}
|
||||
|
||||
send_queue = tevent_queue_create(state, "kdc_udp_proxy");
|
||||
if (send_queue == NULL) {
|
||||
kdc_udp_next_proxy(state);
|
||||
subreq = tdgram_sendto_send(state,
|
||||
state->ev,
|
||||
state->proxy.dgram,
|
||||
state->in.data,
|
||||
state->in.length,
|
||||
NULL);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return;
|
||||
}
|
||||
|
||||
req = tdgram_sendto_queue_send(state,
|
||||
state->kdc->task->event_ctx,
|
||||
dgram,
|
||||
send_queue,
|
||||
state->call->in.data,
|
||||
state->call->in.length,
|
||||
proxy_addr);
|
||||
if (req == NULL) {
|
||||
kdc_udp_next_proxy(state);
|
||||
return;
|
||||
}
|
||||
|
||||
tevent_req_set_callback(req, kdc_udp_proxy_sendto_done, state);
|
||||
tevent_req_set_callback(subreq, kdc_udp_proxy_sendto_done, req);
|
||||
|
||||
/* setup to receive the reply from the proxy */
|
||||
req = tdgram_recvfrom_send(state, state->kdc->task->event_ctx, dgram);
|
||||
if (req == NULL) {
|
||||
kdc_udp_next_proxy(state);
|
||||
subreq = tdgram_recvfrom_send(state, state->ev, state->proxy.dgram);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tevent_req_set_callback(req, kdc_udp_proxy_reply, state);
|
||||
|
||||
tevent_req_set_endtime(req, state->kdc->task->event_ctx,
|
||||
tevent_req_set_callback(subreq, kdc_udp_proxy_recvfrom_done, req);
|
||||
tevent_req_set_endtime(subreq, state->ev,
|
||||
timeval_current_ofs(state->kdc->proxy_timeout, 0));
|
||||
|
||||
DEBUG(4,("kdc_udp_proxy: proxying request to %s\n", state->proxy_ip));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
called when our proxies are not available
|
||||
*/
|
||||
static void kdc_udp_proxy_unavailable(struct kdc_udp_proxy_state *state)
|
||||
{
|
||||
int kret;
|
||||
krb5_data k5_error_blob;
|
||||
struct tevent_req *req;
|
||||
|
||||
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);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
req = tdgram_sendto_queue_send(state,
|
||||
state->kdc->task->event_ctx,
|
||||
state->sock->dgram,
|
||||
state->sock->send_queue,
|
||||
state->call->out.data,
|
||||
state->call->out.length,
|
||||
state->call->src);
|
||||
if (!req) {
|
||||
talloc_free(state);
|
||||
return;
|
||||
}
|
||||
|
||||
tevent_req_set_callback(req, kdc_udp_proxy_reply_done, state);
|
||||
DEBUG(4,("kdc_udp_proxy: proxying request to %s[%s]\n",
|
||||
state->proxy.name.name, state->proxy.ip));
|
||||
}
|
||||
|
||||
/*
|
||||
try the next proxy in the list
|
||||
called when the send of the call to the proxy is complete
|
||||
this is used to get an errors from the sendto()
|
||||
*/
|
||||
static void kdc_udp_next_proxy(struct kdc_udp_proxy_state *state)
|
||||
static void kdc_udp_proxy_sendto_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);
|
||||
struct kdc_udp_proxy_state *state =
|
||||
tevent_req_data(req,
|
||||
struct kdc_udp_proxy_state);
|
||||
ssize_t ret;
|
||||
int sys_errno;
|
||||
|
||||
if (proxy_dnsname == NULL) {
|
||||
kdc_udp_proxy_unavailable(state);
|
||||
return;
|
||||
ret = tdgram_sendto_recv(subreq, &sys_errno);
|
||||
TALLOC_FREE(subreq);
|
||||
if (ret == -1) {
|
||||
DEBUG(4,("kdc_udp_proxy: sendto for %s[%s] gave %d : %s\n",
|
||||
state->proxy.name.name, state->proxy.ip,
|
||||
sys_errno, strerror(sys_errno)));
|
||||
kdc_udp_next_proxy(req);
|
||||
}
|
||||
|
||||
state->next_proxy++;
|
||||
|
||||
make_nbt_name(&name, proxy_dnsname, 0);
|
||||
|
||||
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_udp_next_proxy(state);
|
||||
return;
|
||||
}
|
||||
c->async.fn = kdc_udp_proxy_resolve_done;
|
||||
c->async.private_data = state;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
proxy a UDP kdc request to a writeable DC
|
||||
called when the proxy replies
|
||||
*/
|
||||
void kdc_udp_proxy(struct kdc_server *kdc, struct kdc_udp_socket *sock,
|
||||
struct kdc_udp_call *call, uint16_t port)
|
||||
static void kdc_udp_proxy_recvfrom_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct kdc_udp_proxy_state *state;
|
||||
WERROR werr;
|
||||
struct tevent_req *req =
|
||||
tevent_req_callback_data(subreq,
|
||||
struct tevent_req);
|
||||
struct kdc_udp_proxy_state *state =
|
||||
tevent_req_data(req,
|
||||
struct kdc_udp_proxy_state);
|
||||
int sys_errno;
|
||||
uint8_t *buf;
|
||||
ssize_t len;
|
||||
|
||||
state = talloc_zero(kdc, struct kdc_udp_proxy_state);
|
||||
if (state == NULL) {
|
||||
talloc_free(call);
|
||||
len = tdgram_recvfrom_recv(subreq, &sys_errno,
|
||||
state, &buf, NULL);
|
||||
TALLOC_FREE(subreq);
|
||||
if (len == -1) {
|
||||
DEBUG(4,("kdc_udp_proxy: reply from %s[%s] gave %d : %s\n",
|
||||
state->proxy.name.name, state->proxy.ip,
|
||||
sys_errno, strerror(sys_errno)));
|
||||
kdc_udp_next_proxy(req);
|
||||
return;
|
||||
}
|
||||
|
||||
state->call = talloc_steal(state, call);
|
||||
state->sock = sock;
|
||||
state->kdc = kdc;
|
||||
state->port = port;
|
||||
/*
|
||||
* Check the reply came from the right IP?
|
||||
* As we use connected udp sockets, that should not be needed...
|
||||
*/
|
||||
|
||||
werr = kdc_proxy_get_writeable_dcs(kdc, state, &state->proxy_list);
|
||||
if (!W_ERROR_IS_OK(werr)) {
|
||||
kdc_udp_proxy_unavailable(state);
|
||||
return;
|
||||
}
|
||||
state->out.length = len;
|
||||
state->out.data = buf;
|
||||
|
||||
kdc_udp_next_proxy(state);
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
NTSTATUS kdc_udp_proxy_recv(struct tevent_req *req,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
DATA_BLOB *out)
|
||||
{
|
||||
struct kdc_udp_proxy_state *state =
|
||||
tevent_req_data(req,
|
||||
struct kdc_udp_proxy_state);
|
||||
NTSTATUS status;
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
tevent_req_received(req);
|
||||
return status;
|
||||
}
|
||||
|
||||
out->data = talloc_move(mem_ctx, &state->out.data);
|
||||
out->length = state->out.length;
|
||||
|
||||
tevent_req_received(req);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
struct kdc_tcp_proxy_state {
|
||||
struct kdc_tcp_call *call;
|
||||
|
Loading…
x
Reference in New Issue
Block a user