r13924: Split more prototypes out of include/proto.h + initial work on header
[kamenim/samba.git] / source4 / kdc / kdc.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    KDC Server startup
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
7    Copyright (C) Andrew Tridgell        2005
8    Copyright (C) Stefan Metzmacher      2005
9
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.
14    
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.
19    
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.
23 */
24
25 #include "includes.h"
26 #include "smbd/service_task.h"
27 #include "smbd/service_stream.h"
28 #include "smbd/process_model.h"
29 #include "lib/events/events.h"
30 #include "lib/socket/socket.h"
31 #include "kdc/kdc.h"
32 #include "system/network.h"
33 #include "dlinklist.h"
34 #include "lib/messaging/irpc.h"
35 #include "lib/stream/packet.h"
36 #include "librpc/gen_ndr/samr.h"
37 #include "netif/netif.h"
38
39 /* hold all the info needed to send a reply */
40 struct kdc_reply {
41         struct kdc_reply *next, *prev;
42         struct socket_address *dest;
43         DATA_BLOB packet;
44 };
45
46 typedef BOOL (*kdc_process_fn_t)(struct kdc_server *kdc,
47                                  TALLOC_CTX *mem_ctx, 
48                                  DATA_BLOB *input, 
49                                  DATA_BLOB *reply,
50                                  struct socket_address *peer_addr, 
51                                  struct socket_address *my_addr);
52
53 /* hold information about one kdc socket */
54 struct kdc_socket {
55         struct socket_context *sock;
56         struct kdc_server *kdc;
57         struct fd_event *fde;
58
59         /* a queue of outgoing replies that have been deferred */
60         struct kdc_reply *send_queue;
61
62         kdc_process_fn_t process;
63 };
64 /*
65   state of an open tcp connection
66 */
67 struct kdc_tcp_connection {
68         /* stream connection we belong to */
69         struct stream_connection *conn;
70
71         /* the kdc_server the connection belongs to */
72         struct kdc_server *kdc;
73
74         struct packet_context *packet;
75
76         kdc_process_fn_t process;
77 };
78
79 /*
80   handle fd send events on a KDC socket
81 */
82 static void kdc_send_handler(struct kdc_socket *kdc_socket)
83 {
84         while (kdc_socket->send_queue) {
85                 struct kdc_reply *rep = kdc_socket->send_queue;
86                 NTSTATUS status;
87                 size_t sendlen;
88
89                 status = socket_sendto(kdc_socket->sock, &rep->packet, &sendlen, 0,
90                                        rep->dest);
91                 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
92                         break;
93                 }
94                 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_BUFFER_SIZE)) {
95                         /* Replace with a krb err, response to big */
96                 }
97                 
98                 DLIST_REMOVE(kdc_socket->send_queue, rep);
99                 talloc_free(rep);
100         }
101
102         if (kdc_socket->send_queue == NULL) {
103                 EVENT_FD_NOT_WRITEABLE(kdc_socket->fde);
104         }
105 }
106
107
108 /*
109   handle fd recv events on a KDC socket
110 */
111 static void kdc_recv_handler(struct kdc_socket *kdc_socket)
112 {
113         NTSTATUS status;
114         TALLOC_CTX *tmp_ctx = talloc_new(kdc_socket);
115         DATA_BLOB blob;
116         struct kdc_reply *rep;
117         DATA_BLOB reply;
118         size_t nread, dsize;
119         struct socket_address *src;
120         struct socket_address *my_addr;
121         int ret;
122
123         status = socket_pending(kdc_socket->sock, &dsize);
124         if (!NT_STATUS_IS_OK(status)) {
125                 talloc_free(tmp_ctx);
126                 return;
127         }
128
129         blob = data_blob_talloc(kdc_socket, NULL, dsize);
130         if (blob.data == NULL) {
131                 /* hope this is a temporary low memory condition */
132                 talloc_free(tmp_ctx);
133                 return;
134         }
135
136         status = socket_recvfrom(kdc_socket->sock, blob.data, blob.length, &nread, 0,
137                                  tmp_ctx, &src);
138         if (!NT_STATUS_IS_OK(status)) {
139                 talloc_free(tmp_ctx);
140                 return;
141         }
142         blob.length = nread;
143         
144         DEBUG(10,("Received krb5 UDP packet of length %lu from %s:%u\n", 
145                  (long)blob.length, src->addr, (uint16_t)src->port));
146         
147         my_addr = socket_get_my_addr(kdc_socket->sock, tmp_ctx);
148         if (!my_addr) {
149                 talloc_free(tmp_ctx);
150                 return;
151         }
152
153
154         /* Call krb5 */
155         ret = kdc_socket->process(kdc_socket->kdc, 
156                                   tmp_ctx, 
157                                   &blob,  
158                                   &reply,
159                                   src, my_addr);
160         if (!ret) {
161                 talloc_free(tmp_ctx);
162                 return;
163         }
164
165         /* queue a pending reply */
166         rep = talloc(kdc_socket, struct kdc_reply);
167         if (rep == NULL) {
168                 talloc_free(tmp_ctx);
169                 return;
170         }
171         rep->dest         = talloc_steal(rep, src);
172         rep->packet       = reply;
173         talloc_steal(rep, reply.data);
174
175         if (rep->packet.data == NULL) {
176                 talloc_free(rep);
177                 talloc_free(tmp_ctx);
178                 return;
179         }
180
181         DLIST_ADD_END(kdc_socket->send_queue, rep, struct kdc_reply *);
182         EVENT_FD_WRITEABLE(kdc_socket->fde);
183         talloc_free(tmp_ctx);
184 }
185
186 /*
187   handle fd events on a KDC socket
188 */
189 static void kdc_socket_handler(struct event_context *ev, struct fd_event *fde,
190                                uint16_t flags, void *private)
191 {
192         struct kdc_socket *kdc_socket = talloc_get_type(private, struct kdc_socket);
193         if (flags & EVENT_FD_WRITE) {
194                 kdc_send_handler(kdc_socket);
195         } 
196         if (flags & EVENT_FD_READ) {
197                 kdc_recv_handler(kdc_socket);
198         }
199 }
200
201 static void kdc_tcp_terminate_connection(struct kdc_tcp_connection *kdcconn, const char *reason)
202 {
203         stream_terminate_connection(kdcconn->conn, reason);
204 }
205
206 /*
207   receive a full packet on a KDC connection
208 */
209 static NTSTATUS kdc_tcp_recv(void *private, DATA_BLOB blob)
210 {
211         struct kdc_tcp_connection *kdcconn = talloc_get_type(private, 
212                                                              struct kdc_tcp_connection);
213         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
214         TALLOC_CTX *tmp_ctx = talloc_new(kdcconn);
215         int ret;
216         DATA_BLOB input, reply;
217         struct socket_address *src_addr;
218         struct socket_address *my_addr;
219
220         talloc_steal(tmp_ctx, blob.data);
221
222         src_addr = socket_get_peer_addr(kdcconn->conn->socket, tmp_ctx);
223         if (!src_addr) {
224                 talloc_free(tmp_ctx);
225                 return NT_STATUS_NO_MEMORY;
226         }
227
228         my_addr = socket_get_my_addr(kdcconn->conn->socket, tmp_ctx);
229         if (!my_addr) {
230                 talloc_free(tmp_ctx);
231                 return NT_STATUS_NO_MEMORY;
232         }
233
234         /* Call krb5 */
235         input = data_blob_const(blob.data + 4, blob.length - 4); 
236
237         ret = kdcconn->process(kdcconn->kdc, 
238                                tmp_ctx,
239                                &input,
240                                &reply,
241                                src_addr,
242                                my_addr);
243         if (!ret) {
244                 talloc_free(tmp_ctx);
245                 return NT_STATUS_INTERNAL_ERROR;
246         }
247
248         /* and now encode the reply */
249         blob = data_blob_talloc(kdcconn, NULL, reply.length + 4);
250         if (!blob.data) {
251                 talloc_free(tmp_ctx);
252                 return NT_STATUS_NO_MEMORY;
253         }
254
255         RSIVAL(blob.data, 0, reply.length);
256         memcpy(blob.data + 4, reply.data, reply.length);        
257
258         status = packet_send(kdcconn->packet, blob);
259         if (!NT_STATUS_IS_OK(status)) {
260                 talloc_free(tmp_ctx);
261                 return status;
262         }
263
264         /* the call isn't needed any more */
265         talloc_free(tmp_ctx);
266         return NT_STATUS_OK;
267 }
268
269 /*
270   receive some data on a KDC connection
271 */
272 static void kdc_tcp_recv_handler(struct stream_connection *conn, uint16_t flags)
273 {
274         struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private, 
275                                                              struct kdc_tcp_connection);
276         packet_recv(kdcconn->packet);
277 }
278
279 /*
280   called on a tcp recv error
281 */
282 static void kdc_tcp_recv_error(void *private, NTSTATUS status)
283 {
284         struct kdc_tcp_connection *kdcconn = talloc_get_type(private, struct kdc_tcp_connection);
285         kdc_tcp_terminate_connection(kdcconn, nt_errstr(status));
286 }
287
288 /*
289   called when we can write to a connection
290 */
291 static void kdc_tcp_send(struct stream_connection *conn, uint16_t flags)
292 {
293         struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private, 
294                                                              struct kdc_tcp_connection);
295         packet_queue_run(kdcconn->packet);
296 }
297
298 /**
299    Wrapper for krb5_kdc_process_krb5_request, converting to/from Samba
300    calling conventions
301 */
302
303 static BOOL kdc_process(struct kdc_server *kdc,
304                         TALLOC_CTX *mem_ctx, 
305                         DATA_BLOB *input, 
306                         DATA_BLOB *reply,
307                         struct socket_address *peer_addr, 
308                         struct socket_address *my_addr)
309 {
310         int ret;        
311         krb5_data k5_reply;
312
313         DEBUG(10,("Received KDC packet of length %lu from %s:%d\n", 
314                   (long)input->length - 4, peer_addr->addr, peer_addr->port));
315
316         ret = krb5_kdc_process_krb5_request(kdc->smb_krb5_context->krb5_context, 
317                                             kdc->config,
318                                             input->data, input->length,
319                                             &k5_reply,
320                                             peer_addr->addr,
321                                             peer_addr->sockaddr);
322         if (ret == -1) {
323                 *reply = data_blob(NULL, 0);
324                 return False;
325         }
326         *reply = data_blob_talloc(mem_ctx, k5_reply.data, k5_reply.length);
327         krb5_data_free(&k5_reply);
328         return True;
329 }
330
331 /*
332   called when we get a new connection
333 */
334 static void kdc_tcp_generic_accept(struct stream_connection *conn, kdc_process_fn_t process_fn)
335 {
336         struct kdc_server *kdc = talloc_get_type(conn->private, struct kdc_server);
337         struct kdc_tcp_connection *kdcconn;
338
339         kdcconn = talloc_zero(conn, struct kdc_tcp_connection);
340         if (!kdcconn) {
341                 stream_terminate_connection(conn, "kdc_tcp_accept: out of memory");
342                 return;
343         }
344         kdcconn->conn    = conn;
345         kdcconn->kdc     = kdc;
346         kdcconn->process = process_fn;
347         conn->private    = kdcconn;
348
349         kdcconn->packet = packet_init(kdcconn);
350         if (kdcconn->packet == NULL) {
351                 kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory");
352                 return;
353         }
354         packet_set_private(kdcconn->packet, kdcconn);
355         packet_set_socket(kdcconn->packet, conn->socket);
356         packet_set_callback(kdcconn->packet, kdc_tcp_recv);
357         packet_set_full_request(kdcconn->packet, packet_full_request_u32);
358         packet_set_error_handler(kdcconn->packet, kdc_tcp_recv_error);
359         packet_set_event_context(kdcconn->packet, conn->event.ctx);
360         packet_set_fde(kdcconn->packet, conn->event.fde);
361         packet_set_serialise(kdcconn->packet);
362 }
363
364 static void kdc_tcp_accept(struct stream_connection *conn)
365 {
366         kdc_tcp_generic_accept(conn, kdc_process);
367 }
368
369 static const struct stream_server_ops kdc_tcp_stream_ops = {
370         .name                   = "kdc_tcp",
371         .accept_connection      = kdc_tcp_accept,
372         .recv_handler           = kdc_tcp_recv_handler,
373         .send_handler           = kdc_tcp_send
374 };
375
376 static void kpasswdd_tcp_accept(struct stream_connection *conn)
377 {
378         kdc_tcp_generic_accept(conn, kpasswdd_process);
379 }
380
381 static const struct stream_server_ops kpasswdd_tcp_stream_ops = {
382         .name                   = "kpasswdd_tcp",
383         .accept_connection      = kpasswdd_tcp_accept,
384         .recv_handler           = kdc_tcp_recv_handler,
385         .send_handler           = kdc_tcp_send
386 };
387
388 /*
389   start listening on the given address
390 */
391 static NTSTATUS kdc_add_socket(struct kdc_server *kdc, const char *address)
392 {
393         const struct model_ops *model_ops;
394         struct kdc_socket *kdc_socket;
395         struct kdc_socket *kpasswd_socket;
396         struct socket_address *kdc_address, *kpasswd_address;
397         NTSTATUS status;
398         uint16_t kdc_port = lp_krb5_port();
399         uint16_t kpasswd_port = lp_kpasswd_port();
400
401         kdc_socket = talloc(kdc, struct kdc_socket);
402         NT_STATUS_HAVE_NO_MEMORY(kdc_socket);
403
404         kpasswd_socket = talloc(kdc, struct kdc_socket);
405         NT_STATUS_HAVE_NO_MEMORY(kpasswd_socket);
406
407         status = socket_create("ip", SOCKET_TYPE_DGRAM, &kdc_socket->sock, 0);
408         if (!NT_STATUS_IS_OK(status)) {
409                 talloc_free(kdc_socket);
410                 return status;
411         }
412
413         status = socket_create("ip", SOCKET_TYPE_DGRAM, &kpasswd_socket->sock, 0);
414         if (!NT_STATUS_IS_OK(status)) {
415                 talloc_free(kpasswd_socket);
416                 return status;
417         }
418
419         kdc_socket->kdc = kdc;
420         kdc_socket->send_queue = NULL;
421         kdc_socket->process = kdc_process;
422
423         talloc_steal(kdc_socket, kdc_socket->sock);
424
425         kdc_socket->fde = event_add_fd(kdc->task->event_ctx, kdc, 
426                                        socket_get_fd(kdc_socket->sock), EVENT_FD_READ,
427                                        kdc_socket_handler, kdc_socket);
428
429         kdc_address = socket_address_from_strings(kdc_socket, kdc_socket->sock->backend_name, 
430                                                   address, kdc_port);
431         NT_STATUS_HAVE_NO_MEMORY(kdc_address);
432
433         status = socket_listen(kdc_socket->sock, kdc_address, 0, 0);
434         if (!NT_STATUS_IS_OK(status)) {
435                 DEBUG(0,("Failed to bind to %s:%d UDP for kdc - %s\n", 
436                          address, kdc_port, nt_errstr(status)));
437                 talloc_free(kdc_socket);
438                 return status;
439         }
440
441         kpasswd_socket->kdc = kdc;
442         kpasswd_socket->send_queue = NULL;
443         kpasswd_socket->process = kpasswdd_process;
444
445         talloc_steal(kpasswd_socket, kpasswd_socket->sock);
446
447         kpasswd_socket->fde = event_add_fd(kdc->task->event_ctx, kdc, 
448                                            socket_get_fd(kpasswd_socket->sock), EVENT_FD_READ,
449                                            kdc_socket_handler, kpasswd_socket);
450         
451         kpasswd_address = socket_address_from_strings(kpasswd_socket, kpasswd_socket->sock->backend_name, 
452                                                       address, kpasswd_port);
453         NT_STATUS_HAVE_NO_MEMORY(kpasswd_address);
454
455         status = socket_listen(kpasswd_socket->sock, kpasswd_address, 0, 0);
456         if (!NT_STATUS_IS_OK(status)) {
457                 DEBUG(0,("Failed to bind to %s:%d UDP for kpasswd - %s\n", 
458                          address, kpasswd_port, nt_errstr(status)));
459                 talloc_free(kpasswd_socket);
460                 return status;
461         }
462
463         /* within the kdc task we want to be a single process, so
464            ask for the single process model ops and pass these to the
465            stream_setup_socket() call. */
466         model_ops = process_model_byname("single");
467         if (!model_ops) {
468                 DEBUG(0,("Can't find 'single' process model_ops\n"));
469                 talloc_free(kdc_socket);
470                 return NT_STATUS_INTERNAL_ERROR;
471         }
472
473         status = stream_setup_socket(kdc->task->event_ctx, model_ops, 
474                                      &kdc_tcp_stream_ops, 
475                                      "ip", address, &kdc_port, kdc);
476         if (!NT_STATUS_IS_OK(status)) {
477                 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
478                          address, kdc_port, nt_errstr(status)));
479                 talloc_free(kdc_socket);
480                 return status;
481         }
482
483         status = stream_setup_socket(kdc->task->event_ctx, model_ops, 
484                                      &kpasswdd_tcp_stream_ops, 
485                                      "ip", address, &kpasswd_port, kdc);
486         if (!NT_STATUS_IS_OK(status)) {
487                 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
488                          address, kpasswd_port, nt_errstr(status)));
489                 talloc_free(kdc_socket);
490                 return status;
491         }
492
493         return NT_STATUS_OK;
494 }
495
496
497 /*
498   setup our listening sockets on the configured network interfaces
499 */
500 static NTSTATUS kdc_startup_interfaces(struct kdc_server *kdc)
501 {
502         int num_interfaces = iface_count();
503         TALLOC_CTX *tmp_ctx = talloc_new(kdc);
504         NTSTATUS status;
505         
506         int i;
507         
508         for (i=0; i<num_interfaces; i++) {
509                 const char *address = talloc_strdup(tmp_ctx, iface_n_ip(i));
510                 status = kdc_add_socket(kdc, address);
511                 NT_STATUS_NOT_OK_RETURN(status);
512         }
513
514         talloc_free(tmp_ctx);
515
516         return NT_STATUS_OK;
517 }
518
519 /*
520   startup the kdc task
521 */
522 static void kdc_task_init(struct task_server *task)
523 {
524         struct kdc_server *kdc;
525         NTSTATUS status;
526         krb5_error_code ret;
527
528         switch (lp_server_role()) {
529         case ROLE_STANDALONE:
530                 task_server_terminate(task, "kdc: no KDC required in standalone configuration");
531                 return;
532         case ROLE_DOMAIN_MEMBER:
533                 task_server_terminate(task, "kdc: no KDC required in member server configuration");
534                 return;
535         case ROLE_DOMAIN_PDC:
536         case ROLE_DOMAIN_BDC:
537                 /* Yes, we want a KDC */
538                 break;
539         }
540
541         if (iface_count() == 0) {
542                 task_server_terminate(task, "kdc: no network interfaces configured");
543                 return;
544         }
545
546         kdc = talloc(task, struct kdc_server);
547         if (kdc == NULL) {
548                 task_server_terminate(task, "kdc: out of memory");
549                 return;
550         }
551
552         kdc->task = task;
553
554         /* Setup the KDC configuration */
555         kdc->config = talloc(kdc, krb5_kdc_configuration);
556         if (!kdc->config) {
557                 task_server_terminate(task, "kdc: out of memory");
558                 return;
559         }
560         krb5_kdc_default_config(kdc->config);
561
562         initialize_krb5_error_table();
563
564         ret = smb_krb5_init_context(kdc, &kdc->smb_krb5_context);
565         if (ret) {
566                 DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n", 
567                          error_message(ret)));
568                 task_server_terminate(task, "kdc: krb5_init_context failed");
569                 return; 
570         }
571
572         krb5_add_et_list(kdc->smb_krb5_context->krb5_context, initialize_hdb_error_table_r);
573
574         kdc->config->logf = kdc->smb_krb5_context->logf;
575         kdc->config->db = talloc(kdc->config, struct HDB *);
576         if (!kdc->config->db) {
577                 task_server_terminate(task, "kdc: out of memory");
578                 return;
579         }
580         kdc->config->num_db = 1;
581                 
582         status = kdc_hdb_ldb_create(kdc, kdc->smb_krb5_context->krb5_context, 
583                                     &kdc->config->db[0], NULL);
584         if (!NT_STATUS_IS_OK(status)) {
585                 task_server_terminate(task, "kdc: hdb_ldb_create (setup KDC database) failed");
586                 return; 
587         }
588
589         ret = krb5_kt_register(kdc->smb_krb5_context->krb5_context, &hdb_kt_ops);
590         if(ret) {
591                 task_server_terminate(task, "kdc: failed to register hdb keytab");
592                 return;
593         }
594         /* start listening on the configured network interfaces */
595         status = kdc_startup_interfaces(kdc);
596         if (!NT_STATUS_IS_OK(status)) {
597                 task_server_terminate(task, "kdc failed to setup interfaces");
598                 return;
599         }
600
601         irpc_add_name(task->msg_ctx, "kdc_server");
602 }
603
604
605 /*
606   called on startup of the KDC service 
607 */
608 static NTSTATUS kdc_init(struct event_context *event_ctx, 
609                          const struct model_ops *model_ops)
610 {       
611         return task_server_startup(event_ctx, model_ops, kdc_task_init);
612 }
613
614 /* called at smbd startup - register ourselves as a server service */
615 NTSTATUS server_service_kdc_init(void)
616 {
617         return register_server_service("kdc", kdc_init);
618 }