s4:heimdal: import lorikeet-heimdal-201012010201 (commit 81fe27bcc0148d410ca4617f8759...
[kai/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-2008
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 3 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, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "smbd/service_task.h"
26 #include "smbd/service.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 "lib/tsocket/tsocket.h"
32 #include "libcli/util/tstream.h"
33 #include "system/network.h"
34 #include "../lib/util/dlinklist.h"
35 #include "lib/messaging/irpc.h"
36 #include "lib/stream/packet.h"
37 #include "librpc/gen_ndr/samr.h"
38 #include "librpc/gen_ndr/ndr_irpc.h"
39 #include "librpc/gen_ndr/ndr_krb5pac.h"
40 #include "lib/socket/netif.h"
41 #include "param/param.h"
42 #include "kdc/kdc-glue.h"
43 #include "librpc/gen_ndr/ndr_misc.h"
44 #include "dsdb/samdb/samdb.h"
45 #include "auth/session.h"
46
47 extern struct krb5plugin_windc_ftable windc_plugin_table;
48 extern struct hdb_method hdb_samba4;
49
50 static void kdc_tcp_terminate_connection(struct kdc_tcp_connection *kdcconn, const char *reason)
51 {
52         stream_terminate_connection(kdcconn->conn, reason);
53 }
54
55 static void kdc_tcp_recv(struct stream_connection *conn, uint16_t flags)
56 {
57         struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data,
58                                                              struct kdc_tcp_connection);
59         /* this should never be triggered! */
60         kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_recv: called");
61 }
62
63 static void kdc_tcp_send(struct stream_connection *conn, uint16_t flags)
64 {
65         struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data,
66                                                              struct kdc_tcp_connection);
67         /* this should never be triggered! */
68         kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_send: called");
69 }
70
71 /**
72    Wrapper for krb5_kdc_process_krb5_request, converting to/from Samba
73    calling conventions
74 */
75
76 static enum kdc_process_ret kdc_process(struct kdc_server *kdc,
77                                         TALLOC_CTX *mem_ctx,
78                                         DATA_BLOB *input,
79                                         DATA_BLOB *reply,
80                                         struct tsocket_address *peer_addr,
81                                         struct tsocket_address *my_addr,
82                                         int datagram_reply)
83 {
84         int ret;
85         char *pa;
86         struct sockaddr_storage ss;
87         krb5_data k5_reply;
88         krb5_data_zero(&k5_reply);
89
90         krb5_kdc_update_time(NULL);
91
92         ret = tsocket_address_bsd_sockaddr(peer_addr, (struct sockaddr *) &ss,
93                                 sizeof(struct sockaddr_storage));
94         if (ret < 0) {
95                 return KDC_PROCESS_FAILED;
96         }
97         pa = tsocket_address_string(peer_addr, mem_ctx);
98         if (pa == NULL) {
99                 return KDC_PROCESS_FAILED;
100         }
101
102         DEBUG(10,("Received KDC packet of length %lu from %s\n",
103                                 (long)input->length - 4, pa));
104
105         ret = krb5_kdc_process_krb5_request(kdc->smb_krb5_context->krb5_context,
106                                             kdc->config,
107                                             input->data, input->length,
108                                             &k5_reply,
109                                             pa,
110                                             (struct sockaddr *) &ss,
111                                             datagram_reply);
112         if (ret == -1) {
113                 *reply = data_blob(NULL, 0);
114                 return KDC_PROCESS_FAILED;
115         }
116
117         if (ret == HDB_ERR_NOT_FOUND_HERE) {
118                 *reply = data_blob(NULL, 0);
119                 return KDC_PROCESS_PROXY;
120         }
121
122         if (k5_reply.length) {
123                 *reply = data_blob_talloc(mem_ctx, k5_reply.data, k5_reply.length);
124                 krb5_data_free(&k5_reply);
125         } else {
126                 *reply = data_blob(NULL, 0);
127         }
128         return KDC_PROCESS_OK;
129 }
130
131 static void kdc_tcp_call_writev_done(struct tevent_req *subreq);
132
133 static void kdc_tcp_call_loop(struct tevent_req *subreq)
134 {
135         struct kdc_tcp_connection *kdc_conn = tevent_req_callback_data(subreq,
136                                       struct kdc_tcp_connection);
137         struct kdc_tcp_call *call;
138         NTSTATUS status;
139         enum kdc_process_ret ret;
140
141         call = talloc(kdc_conn, struct kdc_tcp_call);
142         if (call == NULL) {
143                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
144                                 "no memory for kdc_tcp_call");
145                 return;
146         }
147         call->kdc_conn = kdc_conn;
148
149         status = tstream_read_pdu_blob_recv(subreq,
150                                             call,
151                                             &call->in);
152         TALLOC_FREE(subreq);
153         if (!NT_STATUS_IS_OK(status)) {
154                 const char *reason;
155
156                 reason = talloc_asprintf(call, "kdc_tcp_call_loop: "
157                                          "tstream_read_pdu_blob_recv() - %s",
158                                          nt_errstr(status));
159                 if (!reason) {
160                         reason = nt_errstr(status);
161                 }
162
163                 kdc_tcp_terminate_connection(kdc_conn, reason);
164                 return;
165         }
166
167         DEBUG(10,("Received krb5 TCP packet of length %lu from %s\n",
168                  (long) call->in.length,
169                  tsocket_address_string(kdc_conn->conn->remote_address, call)));
170
171         /* skip length header */
172         call->in.data +=4;
173         call->in.length -= 4;
174
175         /* Call krb5 */
176         ret = kdc_conn->kdc_socket->process(kdc_conn->kdc_socket->kdc,
177                                            call,
178                                            &call->in,
179                                            &call->out,
180                                            kdc_conn->conn->remote_address,
181                                            kdc_conn->conn->local_address,
182                                            0 /* Stream */);
183         if (ret == KDC_PROCESS_FAILED) {
184                 kdc_tcp_terminate_connection(kdc_conn,
185                                 "kdc_tcp_call_loop: process function failed");
186                 return;
187         }
188
189         if (ret == KDC_PROCESS_PROXY) {
190                 if (!kdc_conn->kdc_socket->kdc->am_rodc) {
191                         kdc_tcp_terminate_connection(kdc_conn,
192                                                      "kdc_tcp_call_loop: proxying requested when not RODC");
193                         return;
194                 }
195                 kdc_tcp_proxy(kdc_conn->kdc_socket->kdc, kdc_conn, call,
196                               tsocket_address_inet_port(kdc_conn->conn->local_address));
197                 goto done;
198         }
199
200         /* First add the length of the out buffer */
201         RSIVAL(call->out_hdr, 0, call->out.length);
202         call->out_iov[0].iov_base = (char *) call->out_hdr;
203         call->out_iov[0].iov_len = 4;
204
205         call->out_iov[1].iov_base = (char *) call->out.data;
206         call->out_iov[1].iov_len = call->out.length;
207
208         subreq = tstream_writev_queue_send(call,
209                                            kdc_conn->conn->event.ctx,
210                                            kdc_conn->tstream,
211                                            kdc_conn->send_queue,
212                                            call->out_iov, 2);
213         if (subreq == NULL) {
214                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
215                                 "no memory for tstream_writev_queue_send");
216                 return;
217         }
218         tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call);
219
220 done:
221         /*
222          * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
223          * packet_full_request_u32 provides the pdu length then.
224          */
225         subreq = tstream_read_pdu_blob_send(kdc_conn,
226                                             kdc_conn->conn->event.ctx,
227                                             kdc_conn->tstream,
228                                             4, /* initial_read_size */
229                                             packet_full_request_u32,
230                                             kdc_conn);
231         if (subreq == NULL) {
232                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
233                                 "no memory for tstream_read_pdu_blob_send");
234                 return;
235         }
236         tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
237 }
238
239 static void kdc_tcp_call_writev_done(struct tevent_req *subreq)
240 {
241         struct kdc_tcp_call *call = tevent_req_callback_data(subreq,
242                         struct kdc_tcp_call);
243         int sys_errno;
244         int rc;
245
246         rc = tstream_writev_queue_recv(subreq, &sys_errno);
247         TALLOC_FREE(subreq);
248         if (rc == -1) {
249                 const char *reason;
250
251                 reason = talloc_asprintf(call, "kdc_tcp_call_writev_done: "
252                                          "tstream_writev_queue_recv() - %d:%s",
253                                          sys_errno, strerror(sys_errno));
254                 if (!reason) {
255                         reason = "kdc_tcp_call_writev_done: tstream_writev_queue_recv() failed";
256                 }
257
258                 kdc_tcp_terminate_connection(call->kdc_conn, reason);
259                 return;
260         }
261
262         /* We don't care about errors */
263
264         talloc_free(call);
265 }
266
267 /*
268   called when we get a new connection
269 */
270 static void kdc_tcp_accept(struct stream_connection *conn)
271 {
272         struct kdc_socket *kdc_socket;
273         struct kdc_tcp_connection *kdc_conn;
274         struct tevent_req *subreq;
275         int rc;
276
277         kdc_conn = talloc_zero(conn, struct kdc_tcp_connection);
278         if (kdc_conn == NULL) {
279                 stream_terminate_connection(conn,
280                                 "kdc_tcp_accept: out of memory");
281                 return;
282         }
283
284         kdc_conn->send_queue = tevent_queue_create(conn, "kdc_tcp_accept");
285         if (kdc_conn->send_queue == NULL) {
286                 stream_terminate_connection(conn,
287                                 "kdc_tcp_accept: out of memory");
288                 return;
289         }
290
291         kdc_socket = talloc_get_type(conn->private_data, struct kdc_socket);
292
293         TALLOC_FREE(conn->event.fde);
294
295         rc = tstream_bsd_existing_socket(kdc_conn,
296                         socket_get_fd(conn->socket),
297                         &kdc_conn->tstream);
298         if (rc < 0) {
299                 stream_terminate_connection(conn,
300                                 "kdc_tcp_accept: out of memory");
301                 return;
302         }
303
304         kdc_conn->conn = conn;
305         kdc_conn->kdc_socket = kdc_socket;
306         conn->private_data = kdc_conn;
307
308         /*
309          * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
310          * packet_full_request_u32 provides the pdu length then.
311          */
312         subreq = tstream_read_pdu_blob_send(kdc_conn,
313                                             kdc_conn->conn->event.ctx,
314                                             kdc_conn->tstream,
315                                             4, /* initial_read_size */
316                                             packet_full_request_u32,
317                                             kdc_conn);
318         if (subreq == NULL) {
319                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_accept: "
320                                 "no memory for tstream_read_pdu_blob_send");
321                 return;
322         }
323         tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
324 }
325
326 static const struct stream_server_ops kdc_tcp_stream_ops = {
327         .name                   = "kdc_tcp",
328         .accept_connection      = kdc_tcp_accept,
329         .recv_handler           = kdc_tcp_recv,
330         .send_handler           = kdc_tcp_send
331 };
332
333 static void kdc_udp_call_sendto_done(struct tevent_req *subreq);
334
335 static void kdc_udp_call_loop(struct tevent_req *subreq)
336 {
337         struct kdc_udp_socket *sock = tevent_req_callback_data(subreq,
338                                       struct kdc_udp_socket);
339         struct kdc_udp_call *call;
340         uint8_t *buf;
341         ssize_t len;
342         int sys_errno;
343         enum kdc_process_ret ret;
344
345         call = talloc(sock, struct kdc_udp_call);
346         if (call == NULL) {
347                 talloc_free(call);
348                 goto done;
349         }
350
351         len = tdgram_recvfrom_recv(subreq, &sys_errno,
352                                    call, &buf, &call->src);
353         TALLOC_FREE(subreq);
354         if (len == -1) {
355                 talloc_free(call);
356                 goto done;
357         }
358
359         call->in.data = buf;
360         call->in.length = len;
361
362         DEBUG(10,("Received krb5 UDP packet of length %lu from %s\n",
363                  (long)call->in.length,
364                  tsocket_address_string(call->src, call)));
365
366         /* Call krb5 */
367         ret = sock->kdc_socket->process(sock->kdc_socket->kdc,
368                                        call,
369                                        &call->in,
370                                        &call->out,
371                                        call->src,
372                                        sock->kdc_socket->local_address,
373                                        1 /* Datagram */);
374         if (ret == KDC_PROCESS_FAILED) {
375                 talloc_free(call);
376                 goto done;
377         }
378
379         if (ret == KDC_PROCESS_PROXY) {
380                 if (!sock->kdc_socket->kdc->am_rodc) {
381                         DEBUG(0,("kdc_udp_call_loop: proxying requested when not RODC"));
382                         talloc_free(call);
383                         goto done;
384                 }
385                 kdc_udp_proxy(sock->kdc_socket->kdc, sock, call,
386                               tsocket_address_inet_port(sock->kdc_socket->local_address));
387                 goto done;
388         }
389
390         subreq = tdgram_sendto_queue_send(call,
391                                           sock->kdc_socket->kdc->task->event_ctx,
392                                           sock->dgram,
393                                           sock->send_queue,
394                                           call->out.data,
395                                           call->out.length,
396                                           call->src);
397         if (subreq == NULL) {
398                 talloc_free(call);
399                 goto done;
400         }
401         tevent_req_set_callback(subreq, kdc_udp_call_sendto_done, call);
402
403 done:
404         subreq = tdgram_recvfrom_send(sock,
405                                       sock->kdc_socket->kdc->task->event_ctx,
406                                       sock->dgram);
407         if (subreq == NULL) {
408                 task_server_terminate(sock->kdc_socket->kdc->task,
409                                       "no memory for tdgram_recvfrom_send",
410                                       true);
411                 return;
412         }
413         tevent_req_set_callback(subreq, kdc_udp_call_loop, sock);
414 }
415
416 static void kdc_udp_call_sendto_done(struct tevent_req *subreq)
417 {
418         struct kdc_udp_call *call = tevent_req_callback_data(subreq,
419                                        struct kdc_udp_call);
420         ssize_t ret;
421         int sys_errno;
422
423         ret = tdgram_sendto_queue_recv(subreq, &sys_errno);
424
425         /* We don't care about errors */
426
427         talloc_free(call);
428 }
429
430 /*
431   start listening on the given address
432 */
433 static NTSTATUS kdc_add_socket(struct kdc_server *kdc,
434                                const struct model_ops *model_ops,
435                                const char *name,
436                                const char *address,
437                                uint16_t port,
438                                kdc_process_fn_t process,
439                                bool udp_only)
440 {
441         struct kdc_socket *kdc_socket;
442         struct kdc_udp_socket *kdc_udp_socket;
443         struct tevent_req *udpsubreq;
444         NTSTATUS status;
445         int ret;
446
447         kdc_socket = talloc(kdc, struct kdc_socket);
448         NT_STATUS_HAVE_NO_MEMORY(kdc_socket);
449
450         kdc_socket->kdc = kdc;
451         kdc_socket->process = process;
452
453         ret = tsocket_address_inet_from_strings(kdc_socket, "ip",
454                                                 address, port,
455                                                 &kdc_socket->local_address);
456         if (ret != 0) {
457                 status = map_nt_error_from_unix(errno);
458                 return status;
459         }
460
461         if (!udp_only) {
462                 status = stream_setup_socket(kdc->task,
463                                              kdc->task->event_ctx,
464                                              kdc->task->lp_ctx,
465                                              model_ops,
466                                              &kdc_tcp_stream_ops,
467                                              "ip", address, &port,
468                                              lpcfg_socket_options(kdc->task->lp_ctx),
469                                              kdc_socket);
470                 if (!NT_STATUS_IS_OK(status)) {
471                         DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
472                                  address, port, nt_errstr(status)));
473                         talloc_free(kdc_socket);
474                         return status;
475                 }
476         }
477
478         kdc_udp_socket = talloc(kdc_socket, struct kdc_udp_socket);
479         NT_STATUS_HAVE_NO_MEMORY(kdc_udp_socket);
480
481         kdc_udp_socket->kdc_socket = kdc_socket;
482
483         ret = tdgram_inet_udp_socket(kdc_socket->local_address,
484                                      NULL,
485                                      kdc_udp_socket,
486                                      &kdc_udp_socket->dgram);
487         if (ret != 0) {
488                 status = map_nt_error_from_unix(errno);
489                 DEBUG(0,("Failed to bind to %s:%u UDP - %s\n",
490                          address, port, nt_errstr(status)));
491                 return status;
492         }
493
494         kdc_udp_socket->send_queue = tevent_queue_create(kdc_udp_socket,
495                                                          "kdc_udp_send_queue");
496         NT_STATUS_HAVE_NO_MEMORY(kdc_udp_socket->send_queue);
497
498         udpsubreq = tdgram_recvfrom_send(kdc_udp_socket,
499                                          kdc->task->event_ctx,
500                                          kdc_udp_socket->dgram);
501         NT_STATUS_HAVE_NO_MEMORY(udpsubreq);
502         tevent_req_set_callback(udpsubreq, kdc_udp_call_loop, kdc_udp_socket);
503
504         return NT_STATUS_OK;
505 }
506
507
508 /*
509   setup our listening sockets on the configured network interfaces
510 */
511 static NTSTATUS kdc_startup_interfaces(struct kdc_server *kdc, struct loadparm_context *lp_ctx,
512                                        struct interface *ifaces)
513 {
514         const struct model_ops *model_ops;
515         int num_interfaces;
516         TALLOC_CTX *tmp_ctx = talloc_new(kdc);
517         NTSTATUS status;
518         int i;
519         uint16_t kdc_port = lpcfg_krb5_port(lp_ctx);
520         uint16_t kpasswd_port = lpcfg_kpasswd_port(lp_ctx);
521         bool done_wildcard = false;
522
523         /* within the kdc task we want to be a single process, so
524            ask for the single process model ops and pass these to the
525            stream_setup_socket() call. */
526         model_ops = process_model_startup("single");
527         if (!model_ops) {
528                 DEBUG(0,("Can't find 'single' process model_ops\n"));
529                 return NT_STATUS_INTERNAL_ERROR;
530         }
531
532         num_interfaces = iface_count(ifaces);
533
534         /* if we are allowing incoming packets from any address, then
535            we need to bind to the wildcard address */
536         if (!lpcfg_bind_interfaces_only(lp_ctx)) {
537                 if (kdc_port) {
538                         status = kdc_add_socket(kdc, model_ops,
539                                                 "kdc", "0.0.0.0", kdc_port,
540                                                 kdc_process, false);
541                         NT_STATUS_NOT_OK_RETURN(status);
542                 }
543
544                 if (kpasswd_port) {
545                         status = kdc_add_socket(kdc, model_ops,
546                                                 "kpasswd", "0.0.0.0", kpasswd_port,
547                                                 kpasswdd_process, false);
548                         NT_STATUS_NOT_OK_RETURN(status);
549                 }
550                 done_wildcard = true;
551         }
552
553         for (i=0; i<num_interfaces; i++) {
554                 const char *address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
555
556                 if (kdc_port) {
557                         status = kdc_add_socket(kdc, model_ops,
558                                                 "kdc", address, kdc_port,
559                                                 kdc_process, done_wildcard);
560                         NT_STATUS_NOT_OK_RETURN(status);
561                 }
562
563                 if (kpasswd_port) {
564                         status = kdc_add_socket(kdc, model_ops,
565                                                 "kpasswd", address, kpasswd_port,
566                                                 kpasswdd_process, done_wildcard);
567                         NT_STATUS_NOT_OK_RETURN(status);
568                 }
569         }
570
571         talloc_free(tmp_ctx);
572
573         return NT_STATUS_OK;
574 }
575
576
577 static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg,
578                                  struct kdc_check_generic_kerberos *r)
579 {
580         struct PAC_Validate pac_validate;
581         DATA_BLOB srv_sig;
582         struct PAC_SIGNATURE_DATA kdc_sig;
583         struct kdc_server *kdc = talloc_get_type(msg->private_data, struct kdc_server);
584         enum ndr_err_code ndr_err;
585         krb5_enctype etype;
586         int ret;
587         hdb_entry_ex ent;
588         krb5_principal principal;
589         krb5_keyblock keyblock;
590         Key *key;
591
592         /* There is no reply to this request */
593         r->out.generic_reply = data_blob(NULL, 0);
594
595         ndr_err = ndr_pull_struct_blob(&r->in.generic_request, msg, &pac_validate,
596                                        (ndr_pull_flags_fn_t)ndr_pull_PAC_Validate);
597         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
598                 return NT_STATUS_INVALID_PARAMETER;
599         }
600
601         if (pac_validate.MessageType != 3) {
602                 /* We don't implement any other message types - such as certificate validation - yet */
603                 return NT_STATUS_INVALID_PARAMETER;
604         }
605
606         if (pac_validate.ChecksumAndSignature.length != (pac_validate.ChecksumLength + pac_validate.SignatureLength)
607             || pac_validate.ChecksumAndSignature.length < pac_validate.ChecksumLength
608             || pac_validate.ChecksumAndSignature.length < pac_validate.SignatureLength ) {
609                 return NT_STATUS_INVALID_PARAMETER;
610         }
611
612         srv_sig = data_blob_const(pac_validate.ChecksumAndSignature.data,
613                                   pac_validate.ChecksumLength);
614
615         if (pac_validate.SignatureType == CKSUMTYPE_HMAC_MD5) {
616                 etype = ETYPE_ARCFOUR_HMAC_MD5;
617         } else {
618                 ret = krb5_cksumtype_to_enctype(kdc->smb_krb5_context->krb5_context, pac_validate.SignatureType,
619                                                 &etype);
620                 if (ret != 0) {
621                         return NT_STATUS_LOGON_FAILURE;
622                 }
623         }
624
625         ret = krb5_make_principal(kdc->smb_krb5_context->krb5_context, &principal,
626                                   lpcfg_realm(kdc->task->lp_ctx),
627                                   "krbtgt", lpcfg_realm(kdc->task->lp_ctx),
628                                   NULL);
629
630         if (ret != 0) {
631                 return NT_STATUS_NO_MEMORY;
632         }
633
634         ret = kdc->config->db[0]->hdb_fetch_kvno(kdc->smb_krb5_context->krb5_context,
635                                                  kdc->config->db[0],
636                                                  principal,
637                                                  HDB_F_GET_KRBTGT | HDB_F_DECRYPT,
638                                                  0,
639                                                  &ent);
640         
641         if (ret != 0) {
642                 hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent);
643                 krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal);
644
645                 return NT_STATUS_LOGON_FAILURE;
646         }
647
648         ret = hdb_enctype2key(kdc->smb_krb5_context->krb5_context, &ent.entry, etype, &key);
649
650         if (ret != 0) {
651                 hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent);
652                 krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal);
653                 return NT_STATUS_LOGON_FAILURE;
654         }
655
656         keyblock = key->key;
657
658         kdc_sig.type = pac_validate.SignatureType;
659         kdc_sig.signature = data_blob_const(&pac_validate.ChecksumAndSignature.data[pac_validate.ChecksumLength],
660                                             pac_validate.SignatureLength);
661         ret = check_pac_checksum(msg, srv_sig, &kdc_sig,
662                            kdc->smb_krb5_context->krb5_context, &keyblock);
663
664         hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent);
665         krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal);
666
667         if (ret != 0) {
668                 return NT_STATUS_LOGON_FAILURE;
669         }
670
671         return NT_STATUS_OK;
672 }
673
674
675 /*
676   startup the kdc task
677 */
678 static void kdc_task_init(struct task_server *task)
679 {
680         struct kdc_server *kdc;
681         NTSTATUS status;
682         krb5_error_code ret;
683         struct interface *ifaces;
684         int ldb_ret;
685
686         switch (lpcfg_server_role(task->lp_ctx)) {
687         case ROLE_STANDALONE:
688                 task_server_terminate(task, "kdc: no KDC required in standalone configuration", false);
689                 return;
690         case ROLE_DOMAIN_MEMBER:
691                 task_server_terminate(task, "kdc: no KDC required in member server configuration", false);
692                 return;
693         case ROLE_DOMAIN_CONTROLLER:
694                 /* Yes, we want a KDC */
695                 break;
696         }
697
698         load_interfaces(task, lpcfg_interfaces(task->lp_ctx), &ifaces);
699
700         if (iface_count(ifaces) == 0) {
701                 task_server_terminate(task, "kdc: no network interfaces configured", false);
702                 return;
703         }
704
705         task_server_set_title(task, "task[kdc]");
706
707         kdc = talloc_zero(task, struct kdc_server);
708         if (kdc == NULL) {
709                 task_server_terminate(task, "kdc: out of memory", true);
710                 return;
711         }
712
713         kdc->task = task;
714
715
716         /* get a samdb connection */
717         kdc->samdb = samdb_connect(kdc, kdc->task->event_ctx, kdc->task->lp_ctx,
718                                    system_session(kdc->task->lp_ctx), 0);
719         if (!kdc->samdb) {
720                 DEBUG(1,("kdc_task_init: unable to connect to samdb\n"));
721                 task_server_terminate(task, "kdc: krb5_init_context samdb connect failed", true);
722                 return;
723         }
724
725         ldb_ret = samdb_rodc(kdc->samdb, &kdc->am_rodc);
726         if (ldb_ret != LDB_SUCCESS) {
727                 DEBUG(1, ("kdc_task_init: Cannot determine if we are an RODC: %s\n",
728                           ldb_errstring(kdc->samdb)));
729                 task_server_terminate(task, "kdc: krb5_init_context samdb RODC connect failed", true);
730                 return;
731         }
732
733         kdc->proxy_timeout = lpcfg_parm_int(kdc->task->lp_ctx, NULL, "kdc", "proxy timeout", 5);
734
735         initialize_krb5_error_table();
736
737         ret = smb_krb5_init_context(kdc, task->event_ctx, task->lp_ctx, &kdc->smb_krb5_context);
738         if (ret) {
739                 DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n",
740                          error_message(ret)));
741                 task_server_terminate(task, "kdc: krb5_init_context failed", true);
742                 return;
743         }
744
745         krb5_add_et_list(kdc->smb_krb5_context->krb5_context, initialize_hdb_error_table_r);
746
747         ret = krb5_kdc_get_config(kdc->smb_krb5_context->krb5_context,
748                                   &kdc->config);
749         if(ret) {
750                 task_server_terminate(task, "kdc: failed to get KDC configuration", true);
751                 return;
752         }
753
754         kdc->config->logf = kdc->smb_krb5_context->logf;
755         kdc->config->db = talloc(kdc, struct HDB *);
756         if (!kdc->config->db) {
757                 task_server_terminate(task, "kdc: out of memory", true);
758                 return;
759         }
760         kdc->config->num_db = 1;
761
762         /* Register hdb-samba4 hooks for use as a keytab */
763
764         kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context);
765         if (!kdc->base_ctx) {
766                 task_server_terminate(task, "kdc: out of memory", true);
767                 return;
768         }
769
770         kdc->base_ctx->ev_ctx = task->event_ctx;
771         kdc->base_ctx->lp_ctx = task->lp_ctx;
772
773         status = hdb_samba4_create_kdc(kdc->base_ctx,
774                                        kdc->smb_krb5_context->krb5_context,
775                                        &kdc->config->db[0]);
776         if (!NT_STATUS_IS_OK(status)) {
777                 task_server_terminate(task, "kdc: hdb_samba4_create_kdc (setup KDC database) failed", true);
778                 return;
779         }
780
781         ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context,
782                                    PLUGIN_TYPE_DATA, "hdb",
783                                    &hdb_samba4);
784         if(ret) {
785                 task_server_terminate(task, "kdc: failed to register hdb plugin", true);
786                 return;
787         }
788
789         ret = krb5_kt_register(kdc->smb_krb5_context->krb5_context, &hdb_kt_ops);
790         if(ret) {
791                 task_server_terminate(task, "kdc: failed to register keytab plugin", true);
792                 return;
793         }
794
795         /* Register WinDC hooks */
796         ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context,
797                                    PLUGIN_TYPE_DATA, "windc",
798                                    &windc_plugin_table);
799         if(ret) {
800                 task_server_terminate(task, "kdc: failed to register windc plugin", true);
801                 return;
802         }
803
804         ret = krb5_kdc_windc_init(kdc->smb_krb5_context->krb5_context);
805
806         if(ret) {
807                 task_server_terminate(task, "kdc: failed to init windc plugin", true);
808                 return;
809         }
810
811         ret = krb5_kdc_pkinit_config(kdc->smb_krb5_context->krb5_context, kdc->config);
812
813         if(ret) {
814                 task_server_terminate(task, "kdc: failed to init kdc pkinit subsystem", true);
815                 return;
816         }
817
818         /* start listening on the configured network interfaces */
819         status = kdc_startup_interfaces(kdc, task->lp_ctx, ifaces);
820         if (!NT_STATUS_IS_OK(status)) {
821                 task_server_terminate(task, "kdc failed to setup interfaces", true);
822                 return;
823         }
824
825         status = IRPC_REGISTER(task->msg_ctx, irpc, KDC_CHECK_GENERIC_KERBEROS,
826                                kdc_check_generic_kerberos, kdc);
827         if (!NT_STATUS_IS_OK(status)) {
828                 task_server_terminate(task, "kdc failed to setup monitoring", true);
829                 return;
830         }
831
832         irpc_add_name(task->msg_ctx, "kdc_server");
833 }
834
835
836 /* called at smbd startup - register ourselves as a server service */
837 NTSTATUS server_service_kdc_init(void)
838 {
839         return register_server_service("kdc", kdc_task_init);
840 }