2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
7 Copyright (C) Andrew Tridgell 2005
8 Copyright (C) Stefan Metzmacher 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "smbd/service_task.h"
27 #include "smbd/service.h"
28 #include "smbd/service_stream.h"
29 #include "smbd/process_model.h"
30 #include "lib/events/events.h"
31 #include "lib/socket/socket.h"
33 #include "system/network.h"
34 #include "dlinklist.h"
35 #include "lib/messaging/irpc.h"
36 #include "lib/stream/packet.h"
37 #include "librpc/gen_ndr/samr.h"
38 #include "lib/socket/netif.h"
40 /* hold all the info needed to send a reply */
42 struct kdc_reply
*next
, *prev
;
43 struct socket_address
*dest
;
47 typedef BOOL (*kdc_process_fn_t
)(struct kdc_server
*kdc
,
51 struct socket_address
*peer_addr
,
52 struct socket_address
*my_addr
);
54 /* hold information about one kdc socket */
56 struct socket_context
*sock
;
57 struct kdc_server
*kdc
;
60 /* a queue of outgoing replies that have been deferred */
61 struct kdc_reply
*send_queue
;
63 kdc_process_fn_t process
;
66 state of an open tcp connection
68 struct kdc_tcp_connection
{
69 /* stream connection we belong to */
70 struct stream_connection
*conn
;
72 /* the kdc_server the connection belongs to */
73 struct kdc_server
*kdc
;
75 struct packet_context
*packet
;
77 kdc_process_fn_t process
;
81 handle fd send events on a KDC socket
83 static void kdc_send_handler(struct kdc_socket
*kdc_socket
)
85 while (kdc_socket
->send_queue
) {
86 struct kdc_reply
*rep
= kdc_socket
->send_queue
;
90 status
= socket_sendto(kdc_socket
->sock
, &rep
->packet
, &sendlen
,
92 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
95 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_BUFFER_SIZE
)) {
96 /* Replace with a krb err, response to big */
99 DLIST_REMOVE(kdc_socket
->send_queue
, rep
);
103 if (kdc_socket
->send_queue
== NULL
) {
104 EVENT_FD_NOT_WRITEABLE(kdc_socket
->fde
);
110 handle fd recv events on a KDC socket
112 static void kdc_recv_handler(struct kdc_socket
*kdc_socket
)
115 TALLOC_CTX
*tmp_ctx
= talloc_new(kdc_socket
);
117 struct kdc_reply
*rep
;
120 struct socket_address
*src
;
121 struct socket_address
*my_addr
;
124 status
= socket_pending(kdc_socket
->sock
, &dsize
);
125 if (!NT_STATUS_IS_OK(status
)) {
126 talloc_free(tmp_ctx
);
130 blob
= data_blob_talloc(tmp_ctx
, NULL
, dsize
);
131 if (blob
.data
== NULL
) {
132 /* hope this is a temporary low memory condition */
133 talloc_free(tmp_ctx
);
137 status
= socket_recvfrom(kdc_socket
->sock
, blob
.data
, blob
.length
, &nread
,
139 if (!NT_STATUS_IS_OK(status
)) {
140 talloc_free(tmp_ctx
);
145 DEBUG(10,("Received krb5 UDP packet of length %lu from %s:%u\n",
146 (long)blob
.length
, src
->addr
, (uint16_t)src
->port
));
148 my_addr
= socket_get_my_addr(kdc_socket
->sock
, tmp_ctx
);
150 talloc_free(tmp_ctx
);
156 ret
= kdc_socket
->process(kdc_socket
->kdc
,
162 talloc_free(tmp_ctx
);
166 /* queue a pending reply */
167 rep
= talloc(kdc_socket
, struct kdc_reply
);
169 talloc_free(tmp_ctx
);
172 rep
->dest
= talloc_steal(rep
, src
);
174 talloc_steal(rep
, reply
.data
);
176 if (rep
->packet
.data
== NULL
) {
178 talloc_free(tmp_ctx
);
182 DLIST_ADD_END(kdc_socket
->send_queue
, rep
, struct kdc_reply
*);
183 EVENT_FD_WRITEABLE(kdc_socket
->fde
);
184 talloc_free(tmp_ctx
);
188 handle fd events on a KDC socket
190 static void kdc_socket_handler(struct event_context
*ev
, struct fd_event
*fde
,
191 uint16_t flags
, void *private)
193 struct kdc_socket
*kdc_socket
= talloc_get_type(private, struct kdc_socket
);
194 if (flags
& EVENT_FD_WRITE
) {
195 kdc_send_handler(kdc_socket
);
197 if (flags
& EVENT_FD_READ
) {
198 kdc_recv_handler(kdc_socket
);
202 static void kdc_tcp_terminate_connection(struct kdc_tcp_connection
*kdcconn
, const char *reason
)
204 stream_terminate_connection(kdcconn
->conn
, reason
);
208 receive a full packet on a KDC connection
210 static NTSTATUS
kdc_tcp_recv(void *private, DATA_BLOB blob
)
212 struct kdc_tcp_connection
*kdcconn
= talloc_get_type(private,
213 struct kdc_tcp_connection
);
214 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
215 TALLOC_CTX
*tmp_ctx
= talloc_new(kdcconn
);
217 DATA_BLOB input
, reply
;
218 struct socket_address
*src_addr
;
219 struct socket_address
*my_addr
;
221 talloc_steal(tmp_ctx
, blob
.data
);
223 src_addr
= socket_get_peer_addr(kdcconn
->conn
->socket
, tmp_ctx
);
225 talloc_free(tmp_ctx
);
226 return NT_STATUS_NO_MEMORY
;
229 my_addr
= socket_get_my_addr(kdcconn
->conn
->socket
, tmp_ctx
);
231 talloc_free(tmp_ctx
);
232 return NT_STATUS_NO_MEMORY
;
236 input
= data_blob_const(blob
.data
+ 4, blob
.length
- 4);
238 ret
= kdcconn
->process(kdcconn
->kdc
,
245 talloc_free(tmp_ctx
);
246 return NT_STATUS_INTERNAL_ERROR
;
249 /* and now encode the reply */
250 blob
= data_blob_talloc(kdcconn
, NULL
, reply
.length
+ 4);
252 talloc_free(tmp_ctx
);
253 return NT_STATUS_NO_MEMORY
;
256 RSIVAL(blob
.data
, 0, reply
.length
);
257 memcpy(blob
.data
+ 4, reply
.data
, reply
.length
);
259 status
= packet_send(kdcconn
->packet
, blob
);
260 if (!NT_STATUS_IS_OK(status
)) {
261 talloc_free(tmp_ctx
);
265 /* the call isn't needed any more */
266 talloc_free(tmp_ctx
);
271 receive some data on a KDC connection
273 static void kdc_tcp_recv_handler(struct stream_connection
*conn
, uint16_t flags
)
275 struct kdc_tcp_connection
*kdcconn
= talloc_get_type(conn
->private,
276 struct kdc_tcp_connection
);
277 packet_recv(kdcconn
->packet
);
281 called on a tcp recv error
283 static void kdc_tcp_recv_error(void *private, NTSTATUS status
)
285 struct kdc_tcp_connection
*kdcconn
= talloc_get_type(private, struct kdc_tcp_connection
);
286 kdc_tcp_terminate_connection(kdcconn
, nt_errstr(status
));
290 called when we can write to a connection
292 static void kdc_tcp_send(struct stream_connection
*conn
, uint16_t flags
)
294 struct kdc_tcp_connection
*kdcconn
= talloc_get_type(conn
->private,
295 struct kdc_tcp_connection
);
296 packet_queue_run(kdcconn
->packet
);
300 Wrapper for krb5_kdc_process_krb5_request, converting to/from Samba
304 static BOOL
kdc_process(struct kdc_server
*kdc
,
308 struct socket_address
*peer_addr
,
309 struct socket_address
*my_addr
)
314 DEBUG(10,("Received KDC packet of length %lu from %s:%d\n",
315 (long)input
->length
- 4, peer_addr
->addr
, peer_addr
->port
));
317 ret
= krb5_kdc_process_krb5_request(kdc
->smb_krb5_context
->krb5_context
,
319 input
->data
, input
->length
,
322 peer_addr
->sockaddr
);
324 *reply
= data_blob(NULL
, 0);
327 *reply
= data_blob_talloc(mem_ctx
, k5_reply
.data
, k5_reply
.length
);
328 krb5_data_free(&k5_reply
);
333 called when we get a new connection
335 static void kdc_tcp_generic_accept(struct stream_connection
*conn
, kdc_process_fn_t process_fn
)
337 struct kdc_server
*kdc
= talloc_get_type(conn
->private, struct kdc_server
);
338 struct kdc_tcp_connection
*kdcconn
;
340 kdcconn
= talloc_zero(conn
, struct kdc_tcp_connection
);
342 stream_terminate_connection(conn
, "kdc_tcp_accept: out of memory");
345 kdcconn
->conn
= conn
;
347 kdcconn
->process
= process_fn
;
348 conn
->private = kdcconn
;
350 kdcconn
->packet
= packet_init(kdcconn
);
351 if (kdcconn
->packet
== NULL
) {
352 kdc_tcp_terminate_connection(kdcconn
, "kdc_tcp_accept: out of memory");
355 packet_set_private(kdcconn
->packet
, kdcconn
);
356 packet_set_socket(kdcconn
->packet
, conn
->socket
);
357 packet_set_callback(kdcconn
->packet
, kdc_tcp_recv
);
358 packet_set_full_request(kdcconn
->packet
, packet_full_request_u32
);
359 packet_set_error_handler(kdcconn
->packet
, kdc_tcp_recv_error
);
360 packet_set_event_context(kdcconn
->packet
, conn
->event
.ctx
);
361 packet_set_fde(kdcconn
->packet
, conn
->event
.fde
);
362 packet_set_serialise(kdcconn
->packet
);
365 static void kdc_tcp_accept(struct stream_connection
*conn
)
367 kdc_tcp_generic_accept(conn
, kdc_process
);
370 static const struct stream_server_ops kdc_tcp_stream_ops
= {
372 .accept_connection
= kdc_tcp_accept
,
373 .recv_handler
= kdc_tcp_recv_handler
,
374 .send_handler
= kdc_tcp_send
377 static void kpasswdd_tcp_accept(struct stream_connection
*conn
)
379 kdc_tcp_generic_accept(conn
, kpasswdd_process
);
382 static const struct stream_server_ops kpasswdd_tcp_stream_ops
= {
383 .name
= "kpasswdd_tcp",
384 .accept_connection
= kpasswdd_tcp_accept
,
385 .recv_handler
= kdc_tcp_recv_handler
,
386 .send_handler
= kdc_tcp_send
390 start listening on the given address
392 static NTSTATUS
kdc_add_socket(struct kdc_server
*kdc
, const char *address
)
394 const struct model_ops
*model_ops
;
395 struct kdc_socket
*kdc_socket
;
396 struct kdc_socket
*kpasswd_socket
;
397 struct socket_address
*kdc_address
, *kpasswd_address
;
399 uint16_t kdc_port
= lp_krb5_port();
400 uint16_t kpasswd_port
= lp_kpasswd_port();
402 kdc_socket
= talloc(kdc
, struct kdc_socket
);
403 NT_STATUS_HAVE_NO_MEMORY(kdc_socket
);
405 kpasswd_socket
= talloc(kdc
, struct kdc_socket
);
406 NT_STATUS_HAVE_NO_MEMORY(kpasswd_socket
);
408 status
= socket_create("ip", SOCKET_TYPE_DGRAM
, &kdc_socket
->sock
, 0);
409 if (!NT_STATUS_IS_OK(status
)) {
410 talloc_free(kdc_socket
);
414 status
= socket_create("ip", SOCKET_TYPE_DGRAM
, &kpasswd_socket
->sock
, 0);
415 if (!NT_STATUS_IS_OK(status
)) {
416 talloc_free(kpasswd_socket
);
420 kdc_socket
->kdc
= kdc
;
421 kdc_socket
->send_queue
= NULL
;
422 kdc_socket
->process
= kdc_process
;
424 talloc_steal(kdc_socket
, kdc_socket
->sock
);
426 kdc_socket
->fde
= event_add_fd(kdc
->task
->event_ctx
, kdc
,
427 socket_get_fd(kdc_socket
->sock
), EVENT_FD_READ
,
428 kdc_socket_handler
, kdc_socket
);
430 kdc_address
= socket_address_from_strings(kdc_socket
, kdc_socket
->sock
->backend_name
,
432 NT_STATUS_HAVE_NO_MEMORY(kdc_address
);
434 status
= socket_listen(kdc_socket
->sock
, kdc_address
, 0, 0);
435 if (!NT_STATUS_IS_OK(status
)) {
436 DEBUG(0,("Failed to bind to %s:%d UDP for kdc - %s\n",
437 address
, kdc_port
, nt_errstr(status
)));
438 talloc_free(kdc_socket
);
442 kpasswd_socket
->kdc
= kdc
;
443 kpasswd_socket
->send_queue
= NULL
;
444 kpasswd_socket
->process
= kpasswdd_process
;
446 talloc_steal(kpasswd_socket
, kpasswd_socket
->sock
);
448 kpasswd_socket
->fde
= event_add_fd(kdc
->task
->event_ctx
, kdc
,
449 socket_get_fd(kpasswd_socket
->sock
), EVENT_FD_READ
,
450 kdc_socket_handler
, kpasswd_socket
);
452 kpasswd_address
= socket_address_from_strings(kpasswd_socket
, kpasswd_socket
->sock
->backend_name
,
453 address
, kpasswd_port
);
454 NT_STATUS_HAVE_NO_MEMORY(kpasswd_address
);
456 status
= socket_listen(kpasswd_socket
->sock
, kpasswd_address
, 0, 0);
457 if (!NT_STATUS_IS_OK(status
)) {
458 DEBUG(0,("Failed to bind to %s:%d UDP for kpasswd - %s\n",
459 address
, kpasswd_port
, nt_errstr(status
)));
460 talloc_free(kpasswd_socket
);
464 /* within the kdc task we want to be a single process, so
465 ask for the single process model ops and pass these to the
466 stream_setup_socket() call. */
467 model_ops
= process_model_byname("single");
469 DEBUG(0,("Can't find 'single' process model_ops\n"));
470 talloc_free(kdc_socket
);
471 return NT_STATUS_INTERNAL_ERROR
;
474 status
= stream_setup_socket(kdc
->task
->event_ctx
, model_ops
,
476 "ip", address
, &kdc_port
, kdc
);
477 if (!NT_STATUS_IS_OK(status
)) {
478 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
479 address
, kdc_port
, nt_errstr(status
)));
480 talloc_free(kdc_socket
);
484 status
= stream_setup_socket(kdc
->task
->event_ctx
, model_ops
,
485 &kpasswdd_tcp_stream_ops
,
486 "ip", address
, &kpasswd_port
, kdc
);
487 if (!NT_STATUS_IS_OK(status
)) {
488 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
489 address
, kpasswd_port
, nt_errstr(status
)));
490 talloc_free(kdc_socket
);
499 setup our listening sockets on the configured network interfaces
501 static NTSTATUS
kdc_startup_interfaces(struct kdc_server
*kdc
)
503 int num_interfaces
= iface_count();
504 TALLOC_CTX
*tmp_ctx
= talloc_new(kdc
);
509 for (i
=0; i
<num_interfaces
; i
++) {
510 const char *address
= talloc_strdup(tmp_ctx
, iface_n_ip(i
));
511 status
= kdc_add_socket(kdc
, address
);
512 NT_STATUS_NOT_OK_RETURN(status
);
515 talloc_free(tmp_ctx
);
523 static void kdc_task_init(struct task_server
*task
)
525 struct kdc_server
*kdc
;
529 switch (lp_server_role()) {
530 case ROLE_STANDALONE
:
531 task_server_terminate(task
, "kdc: no KDC required in standalone configuration");
533 case ROLE_DOMAIN_MEMBER
:
534 task_server_terminate(task
, "kdc: no KDC required in member server configuration");
536 case ROLE_DOMAIN_PDC
:
537 case ROLE_DOMAIN_BDC
:
538 /* Yes, we want a KDC */
542 if (iface_count() == 0) {
543 task_server_terminate(task
, "kdc: no network interfaces configured");
547 task_server_set_title(task
, "task[kdc]");
549 kdc
= talloc(task
, struct kdc_server
);
551 task_server_terminate(task
, "kdc: out of memory");
557 /* Setup the KDC configuration */
558 kdc
->config
= talloc(kdc
, krb5_kdc_configuration
);
560 task_server_terminate(task
, "kdc: out of memory");
563 krb5_kdc_default_config(kdc
->config
);
565 initialize_krb5_error_table();
567 ret
= smb_krb5_init_context(kdc
, &kdc
->smb_krb5_context
);
569 DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n",
570 error_message(ret
)));
571 task_server_terminate(task
, "kdc: krb5_init_context failed");
575 krb5_add_et_list(kdc
->smb_krb5_context
->krb5_context
, initialize_hdb_error_table_r
);
577 kdc
->config
->logf
= kdc
->smb_krb5_context
->logf
;
578 kdc
->config
->db
= talloc(kdc
->config
, struct HDB
*);
579 if (!kdc
->config
->db
) {
580 task_server_terminate(task
, "kdc: out of memory");
583 kdc
->config
->num_db
= 1;
585 status
= kdc_hdb_ldb_create(kdc
, kdc
->smb_krb5_context
->krb5_context
,
586 &kdc
->config
->db
[0], NULL
);
587 if (!NT_STATUS_IS_OK(status
)) {
588 task_server_terminate(task
, "kdc: hdb_ldb_create (setup KDC database) failed");
592 ret
= krb5_kt_register(kdc
->smb_krb5_context
->krb5_context
, &hdb_kt_ops
);
594 task_server_terminate(task
, "kdc: failed to register hdb keytab");
597 /* start listening on the configured network interfaces */
598 status
= kdc_startup_interfaces(kdc
);
599 if (!NT_STATUS_IS_OK(status
)) {
600 task_server_terminate(task
, "kdc failed to setup interfaces");
604 irpc_add_name(task
->msg_ctx
, "kdc_server");
609 called on startup of the KDC service
611 static NTSTATUS
kdc_init(struct event_context
*event_ctx
,
612 const struct model_ops
*model_ops
)
614 return task_server_startup(event_ctx
, model_ops
, kdc_task_init
);
617 /* called at smbd startup - register ourselves as a server service */
618 NTSTATUS
server_service_kdc_init(void)
620 return register_server_service("kdc", kdc_init
);