2 Unix SMB/CIFS implementation.
4 KDC Server request proxying
6 Copyright (C) Andrew Tridgell 2010
7 Copyright (C) Andrew Bartlett 2010
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "smbd/process_model.h"
25 #include "lib/tsocket/tsocket.h"
26 #include "libcli/util/tstream.h"
27 #include "system/network.h"
28 #include "param/param.h"
29 #include "lib/stream/packet.h"
30 #include "kdc/kdc-glue.h"
32 #include "librpc/gen_ndr/drsblobs.h"
33 #include "dsdb/schema/schema.h"
34 #include "dsdb/common/proto.h"
35 #include "libcli/composite/composite.h"
36 #include "libcli/resolve/resolve.h"
40 get a list of our replication partners from repsFrom, returning it in *proxy_list
42 static WERROR
kdc_proxy_get_writeable_dcs(struct kdc_server
*kdc
, TALLOC_CTX
*mem_ctx
, char ***proxy_list
)
46 struct repsFromToBlob
*reps
;
48 werr
= dsdb_loadreps(kdc
->samdb
, mem_ctx
, ldb_get_default_basedn(kdc
->samdb
), "repsFrom", &reps
, &count
);
49 W_ERROR_NOT_OK_RETURN(werr
);
52 /* we don't have any DCs to replicate with. Very
54 DEBUG(1,(__location__
": No replication sources for RODC in KDC proxy\n"));
56 return WERR_DS_DRA_NO_REPLICA
;
59 (*proxy_list
) = talloc_array(mem_ctx
, char *, count
+1);
60 W_ERROR_HAVE_NO_MEMORY_AND_FREE(*proxy_list
, reps
);
62 talloc_steal(*proxy_list
, reps
);
64 for (i
=0; i
<count
; i
++) {
65 const char *dns_name
= NULL
;
66 if (reps
->version
== 1) {
67 dns_name
= reps
->ctr
.ctr1
.other_info
->dns_name
;
68 } else if (reps
->version
== 2) {
69 dns_name
= reps
->ctr
.ctr2
.other_info
->dns_name1
;
71 (*proxy_list
)[i
] = talloc_strdup(*proxy_list
, dns_name
);
72 W_ERROR_HAVE_NO_MEMORY_AND_FREE((*proxy_list
)[i
], *proxy_list
);
74 (*proxy_list
)[i
] = NULL
;
82 struct kdc_udp_proxy_state
{
83 struct kdc_udp_call
*call
;
84 struct kdc_udp_socket
*sock
;
85 struct kdc_server
*kdc
;
93 static void kdc_udp_next_proxy(struct kdc_udp_proxy_state
*state
);
96 called when the send of the call to the proxy is complete
97 this is used to get an errors from the sendto()
99 static void kdc_udp_proxy_sendto_done(struct tevent_req
*req
)
101 struct kdc_udp_proxy_state
*state
= tevent_req_callback_data(req
,
102 struct kdc_udp_proxy_state
);
106 ret
= tdgram_sendto_queue_recv(req
, &sys_errno
);
110 DEBUG(4,("kdc_udp_proxy: sendto for %s gave %d : %s\n",
111 state
->proxy_ip
, sys_errno
, strerror(sys_errno
)));
112 kdc_udp_next_proxy(state
);
117 called when the send of the reply to the client is complete
118 this is used to get an errors from the sendto()
120 static void kdc_udp_proxy_reply_done(struct tevent_req
*req
)
122 struct kdc_udp_proxy_state
*state
= tevent_req_callback_data(req
,
123 struct kdc_udp_proxy_state
);
127 ret
= tdgram_sendto_queue_recv(req
, &sys_errno
);
129 DEBUG(3,("kdc_udp_proxy: reply sendto gave %d : %s\n",
130 sys_errno
, strerror(sys_errno
)));
133 /* all done - we can destroy the proxy state */
140 called when the proxy replies
142 static void kdc_udp_proxy_reply(struct tevent_req
*req
)
144 struct kdc_udp_proxy_state
*state
= tevent_req_callback_data(req
,
145 struct kdc_udp_proxy_state
);
148 struct tsocket_address
*src
;
151 len
= tdgram_recvfrom_recv(req
, &sys_errno
,
155 DEBUG(4,("kdc_udp_proxy: reply from %s gave %d : %s\n",
156 state
->proxy_ip
, sys_errno
, strerror(sys_errno
)));
157 kdc_udp_next_proxy(state
);
161 state
->call
->out
.length
= len
;
162 state
->call
->out
.data
= buf
;
164 /* TODO: check the reply came from the right IP? */
166 req
= tdgram_sendto_queue_send(state
,
167 state
->kdc
->task
->event_ctx
,
169 state
->sock
->send_queue
,
170 state
->call
->out
.data
,
171 state
->call
->out
.length
,
174 kdc_udp_next_proxy(state
);
178 tevent_req_set_callback(req
, kdc_udp_proxy_reply_done
, state
);
183 called when we've resolved the name of a proxy
185 static void kdc_udp_proxy_resolve_done(struct composite_context
*c
)
187 struct kdc_udp_proxy_state
*state
;
189 struct tevent_req
*req
;
190 struct tsocket_address
*local_addr
, *proxy_addr
;
192 struct tdgram_context
*dgram
;
193 struct tevent_queue
*send_queue
;
195 state
= talloc_get_type(c
->async
.private_data
, struct kdc_udp_proxy_state
);
197 status
= resolve_name_recv(c
, state
, &state
->proxy_ip
);
198 if (!NT_STATUS_IS_OK(status
)) {
199 DEBUG(0,("Unable to resolve proxy\n"));
200 kdc_udp_next_proxy(state
);
204 /* get an address for us to use locally */
205 ret
= tsocket_address_inet_from_strings(state
, "ip", NULL
, 0, &local_addr
);
207 kdc_udp_next_proxy(state
);
211 ret
= tsocket_address_inet_from_strings(state
, "ip",
212 state
->proxy_ip
, state
->port
, &proxy_addr
);
214 kdc_udp_next_proxy(state
);
218 /* create a socket for us to work on */
219 ret
= tdgram_inet_udp_socket(local_addr
, proxy_addr
, state
, &dgram
);
221 kdc_udp_next_proxy(state
);
225 send_queue
= tevent_queue_create(state
, "kdc_udp_proxy");
226 if (send_queue
== NULL
) {
227 kdc_udp_next_proxy(state
);
231 req
= tdgram_sendto_queue_send(state
,
232 state
->kdc
->task
->event_ctx
,
235 state
->call
->in
.data
,
236 state
->call
->in
.length
,
239 kdc_udp_next_proxy(state
);
243 tevent_req_set_callback(req
, kdc_udp_proxy_sendto_done
, state
);
245 /* setup to receive the reply from the proxy */
246 req
= tdgram_recvfrom_send(state
, state
->kdc
->task
->event_ctx
, dgram
);
248 kdc_udp_next_proxy(state
);
252 tevent_req_set_callback(req
, kdc_udp_proxy_reply
, state
);
254 tevent_req_set_endtime(req
, state
->kdc
->task
->event_ctx
,
255 timeval_current_ofs(state
->kdc
->proxy_timeout
, 0));
257 DEBUG(4,("kdc_udp_proxy: proxying request to %s\n", state
->proxy_ip
));
262 called when our proxies are not available
264 static void kdc_udp_proxy_unavailable(struct kdc_udp_proxy_state
*state
)
267 krb5_data k5_error_blob
;
268 struct tevent_req
*req
;
270 kret
= krb5_mk_error(state
->kdc
->smb_krb5_context
->krb5_context
,
271 KRB5KDC_ERR_SVC_UNAVAILABLE
, NULL
, NULL
,
272 NULL
, NULL
, NULL
, NULL
, &k5_error_blob
);
274 DEBUG(2,(__location__
": Unable to form krb5 error reply\n"));
279 state
->call
->out
= data_blob_talloc(state
, k5_error_blob
.data
, k5_error_blob
.length
);
280 krb5_data_free(&k5_error_blob
);
281 if (!state
->call
->out
.data
) {
286 req
= tdgram_sendto_queue_send(state
,
287 state
->kdc
->task
->event_ctx
,
289 state
->sock
->send_queue
,
290 state
->call
->out
.data
,
291 state
->call
->out
.length
,
298 tevent_req_set_callback(req
, kdc_udp_proxy_reply_done
, state
);
302 try the next proxy in the list
304 static void kdc_udp_next_proxy(struct kdc_udp_proxy_state
*state
)
306 const char *proxy_dnsname
= state
->proxy_list
[state
->next_proxy
];
307 struct nbt_name name
;
308 struct composite_context
*c
;
310 if (proxy_dnsname
== NULL
) {
311 kdc_udp_proxy_unavailable(state
);
317 make_nbt_name(&name
, proxy_dnsname
, 0);
319 c
= resolve_name_ex_send(lpcfg_resolve_context(state
->kdc
->task
->lp_ctx
),
321 RESOLVE_NAME_FLAG_FORCE_DNS
,
324 state
->kdc
->task
->event_ctx
);
326 kdc_udp_next_proxy(state
);
329 c
->async
.fn
= kdc_udp_proxy_resolve_done
;
330 c
->async
.private_data
= state
;
335 proxy a UDP kdc request to a writeable DC
337 void kdc_udp_proxy(struct kdc_server
*kdc
, struct kdc_udp_socket
*sock
,
338 struct kdc_udp_call
*call
, uint16_t port
)
340 struct kdc_udp_proxy_state
*state
;
343 state
= talloc_zero(kdc
, struct kdc_udp_proxy_state
);
349 state
->call
= talloc_steal(state
, call
);
354 werr
= kdc_proxy_get_writeable_dcs(kdc
, state
, &state
->proxy_list
);
355 if (!W_ERROR_IS_OK(werr
)) {
356 kdc_udp_proxy_unavailable(state
);
360 kdc_udp_next_proxy(state
);
364 struct kdc_tcp_proxy_state
{
365 struct kdc_tcp_call
*call
;
366 struct kdc_tcp_connection
*kdc_conn
;
367 struct kdc_server
*kdc
;
371 const char *proxy_ip
;
374 static void kdc_tcp_next_proxy(struct kdc_tcp_proxy_state
*state
);
377 called when the send of the proxied reply to the client is done
379 static void kdc_tcp_proxy_reply_done(struct tevent_req
*req
)
381 struct kdc_tcp_proxy_state
*state
= tevent_req_callback_data(req
,
382 struct kdc_tcp_proxy_state
);
385 ret
= tstream_writev_queue_recv(req
, &sys_errno
);
387 DEBUG(4,("kdc_tcp_proxy: writev of reply gave %d : %s\n",
388 sys_errno
, strerror(sys_errno
)));
395 called when the recv of the proxied reply is done
397 static void kdc_tcp_proxy_recv_done(struct tevent_req
*req
)
399 struct kdc_tcp_proxy_state
*state
= tevent_req_callback_data(req
,
400 struct kdc_tcp_proxy_state
);
403 status
= tstream_read_pdu_blob_recv(req
,
408 if (!NT_STATUS_IS_OK(status
)) {
409 kdc_tcp_next_proxy(state
);
414 /* send the reply to the original caller */
416 state
->call
->out_iov
[0].iov_base
= (char *)state
->call
->out
.data
;
417 state
->call
->out_iov
[0].iov_len
= state
->call
->out
.length
;
419 req
= tstream_writev_queue_send(state
,
420 state
->kdc_conn
->conn
->event
.ctx
,
421 state
->kdc_conn
->tstream
,
422 state
->kdc_conn
->send_queue
,
423 state
->call
->out_iov
, 1);
425 kdc_tcp_next_proxy(state
);
429 tevent_req_set_callback(req
, kdc_tcp_proxy_reply_done
, state
);
433 called when the send of the proxied packet is done
435 static void kdc_tcp_proxy_send_done(struct tevent_req
*req
)
437 struct kdc_tcp_proxy_state
*state
= tevent_req_callback_data(req
,
438 struct kdc_tcp_proxy_state
);
441 ret
= tstream_writev_queue_recv(req
, &sys_errno
);
444 kdc_tcp_next_proxy(state
);
449 called when we've connected to the proxy
451 static void kdc_tcp_proxy_connect_done(struct tevent_req
*req
)
453 struct kdc_tcp_proxy_state
*state
= tevent_req_callback_data(req
,
454 struct kdc_tcp_proxy_state
);
456 struct tstream_context
*stream
;
457 struct tevent_queue
*send_queue
;
460 ret
= tstream_inet_tcp_connect_recv(req
, &sys_errno
, state
, &stream
, NULL
);
464 kdc_tcp_next_proxy(state
);
468 RSIVAL(state
->call
->out_hdr
, 0, state
->call
->in
.length
);
469 state
->call
->out_iov
[0].iov_base
= (char *)state
->call
->out_hdr
;
470 state
->call
->out_iov
[0].iov_len
= 4;
471 state
->call
->out_iov
[1].iov_base
= (char *) state
->call
->in
.data
;
472 state
->call
->out_iov
[1].iov_len
= state
->call
->in
.length
;
474 send_queue
= tevent_queue_create(state
, "kdc_tcp_proxy");
475 if (send_queue
== NULL
) {
476 kdc_tcp_next_proxy(state
);
480 req
= tstream_writev_queue_send(state
,
481 state
->kdc_conn
->conn
->event
.ctx
,
484 state
->call
->out_iov
, 2);
486 kdc_tcp_next_proxy(state
);
490 tevent_req_set_callback(req
, kdc_tcp_proxy_send_done
, state
);
492 req
= tstream_read_pdu_blob_send(state
,
493 state
->kdc_conn
->conn
->event
.ctx
,
495 4, /* initial_read_size */
496 packet_full_request_u32
,
499 kdc_tcp_next_proxy(state
);
503 tevent_req_set_callback(req
, kdc_tcp_proxy_recv_done
, state
);
504 tevent_req_set_endtime(req
, state
->kdc
->task
->event_ctx
,
505 timeval_current_ofs(state
->kdc
->proxy_timeout
, 0));
511 called when name resolution for a proxy is done
513 static void kdc_tcp_proxy_resolve_done(struct composite_context
*c
)
515 struct kdc_tcp_proxy_state
*state
;
517 struct tevent_req
*req
;
518 struct tsocket_address
*local_addr
, *proxy_addr
;
521 state
= talloc_get_type(c
->async
.private_data
, struct kdc_tcp_proxy_state
);
523 status
= resolve_name_recv(c
, state
, &state
->proxy_ip
);
524 if (!NT_STATUS_IS_OK(status
)) {
525 kdc_tcp_next_proxy(state
);
529 /* get an address for us to use locally */
530 ret
= tsocket_address_inet_from_strings(state
, "ip", NULL
, 0, &local_addr
);
532 kdc_tcp_next_proxy(state
);
536 ret
= tsocket_address_inet_from_strings(state
, "ip",
537 state
->proxy_ip
, state
->port
, &proxy_addr
);
539 kdc_tcp_next_proxy(state
);
543 /* connect to the proxy */
544 req
= tstream_inet_tcp_connect_send(state
, state
->kdc
->task
->event_ctx
, local_addr
, proxy_addr
);
546 kdc_tcp_next_proxy(state
);
550 tevent_req_set_callback(req
, kdc_tcp_proxy_connect_done
, state
);
552 tevent_req_set_endtime(req
, state
->kdc
->task
->event_ctx
,
553 timeval_current_ofs(state
->kdc
->proxy_timeout
, 0));
555 DEBUG(4,("kdc_tcp_proxy: proxying request to %s\n", state
->proxy_ip
));
560 called when our proxies are not available
562 static void kdc_tcp_proxy_unavailable(struct kdc_tcp_proxy_state
*state
)
565 krb5_data k5_error_blob
;
566 struct tevent_req
*req
;
568 kret
= krb5_mk_error(state
->kdc
->smb_krb5_context
->krb5_context
,
569 KRB5KDC_ERR_SVC_UNAVAILABLE
, NULL
, NULL
,
570 NULL
, NULL
, NULL
, NULL
, &k5_error_blob
);
572 DEBUG(2,(__location__
": Unable to form krb5 error reply\n"));
578 state
->call
->out
= data_blob_talloc(state
, k5_error_blob
.data
, k5_error_blob
.length
);
579 krb5_data_free(&k5_error_blob
);
580 if (!state
->call
->out
.data
) {
585 state
->call
->out_iov
[0].iov_base
= (char *)state
->call
->out
.data
;
586 state
->call
->out_iov
[0].iov_len
= state
->call
->out
.length
;
588 req
= tstream_writev_queue_send(state
,
589 state
->kdc_conn
->conn
->event
.ctx
,
590 state
->kdc_conn
->tstream
,
591 state
->kdc_conn
->send_queue
,
592 state
->call
->out_iov
, 1);
598 tevent_req_set_callback(req
, kdc_tcp_proxy_reply_done
, state
);
602 try the next proxy in the list
604 static void kdc_tcp_next_proxy(struct kdc_tcp_proxy_state
*state
)
606 const char *proxy_dnsname
= state
->proxy_list
[state
->next_proxy
];
607 struct nbt_name name
;
608 struct composite_context
*c
;
610 if (proxy_dnsname
== NULL
) {
611 kdc_tcp_proxy_unavailable(state
);
617 make_nbt_name(&name
, proxy_dnsname
, 0);
619 c
= resolve_name_ex_send(lpcfg_resolve_context(state
->kdc
->task
->lp_ctx
),
621 RESOLVE_NAME_FLAG_FORCE_DNS
,
624 state
->kdc
->task
->event_ctx
);
626 kdc_tcp_next_proxy(state
);
629 c
->async
.fn
= kdc_tcp_proxy_resolve_done
;
630 c
->async
.private_data
= state
;
635 proxy a TCP kdc request to a writeable DC
637 void kdc_tcp_proxy(struct kdc_server
*kdc
, struct kdc_tcp_connection
*kdc_conn
,
638 struct kdc_tcp_call
*call
, uint16_t port
)
640 struct kdc_tcp_proxy_state
*state
;
643 state
= talloc_zero(kdc_conn
, struct kdc_tcp_proxy_state
);
645 state
->call
= talloc_steal(state
, call
);
646 state
->kdc_conn
= kdc_conn
;
650 werr
= kdc_proxy_get_writeable_dcs(kdc
, state
, &state
->proxy_list
);
651 if (!W_ERROR_IS_OK(werr
)) {
652 kdc_tcp_proxy_unavailable(state
);
656 kdc_tcp_next_proxy(state
);