X-Git-Url: http://git.samba.org/samba.git/?p=jelmer%2Fsamba4-debian.git;a=blobdiff_plain;f=source%2Fkdc%2Fkdc.c;h=6c1f20bf134a3f32c66b5408be3f56af3eba52b3;hp=2fd5674f79456bcc0d2441b4001ce58a3e94f428;hb=7780bf285fdfc30f89409d0436bad0d4b6de5cd4;hpb=526f20bbecc9bbd607595637c15fc4001d3f0c70 diff --git a/source/kdc/kdc.c b/source/kdc/kdc.c index 2fd5674f7..6c1f20bf1 100644 --- a/source/kdc/kdc.c +++ b/source/kdc/kdc.c @@ -9,7 +9,7 @@ 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 - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -18,8 +18,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" @@ -31,11 +30,19 @@ #include "lib/socket/socket.h" #include "kdc/kdc.h" #include "system/network.h" -#include "dlinklist.h" +#include "lib/util/dlinklist.h" #include "lib/messaging/irpc.h" #include "lib/stream/packet.h" #include "librpc/gen_ndr/samr.h" -#include "netif/netif.h" +#include "lib/socket/netif.h" +#include "heimdal/kdc/windc_plugin.h" +#include "heimdal/lib/krb5/krb5_locl.h" +#include "heimdal/kdc/kdc_locl.h" +#include "param/param.h" + + +/* Disgusting hack to get a mem_ctx into the hdb plugin, when used as a keytab */ +TALLOC_CTX *kdc_mem_ctx; /* hold all the info needed to send a reply */ struct kdc_reply { @@ -44,12 +51,13 @@ struct kdc_reply { DATA_BLOB packet; }; -typedef BOOL (*kdc_process_fn_t)(struct kdc_server *kdc, +typedef bool (*kdc_process_fn_t)(struct kdc_server *kdc, TALLOC_CTX *mem_ctx, DATA_BLOB *input, DATA_BLOB *reply, struct socket_address *peer_addr, - struct socket_address *my_addr); + struct socket_address *my_addr, + int datagram); /* hold information about one kdc socket */ struct kdc_socket { @@ -87,7 +95,7 @@ static void kdc_send_handler(struct kdc_socket *kdc_socket) NTSTATUS status; size_t sendlen; - status = socket_sendto(kdc_socket->sock, &rep->packet, &sendlen, 0, + status = socket_sendto(kdc_socket->sock, &rep->packet, &sendlen, rep->dest); if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { break; @@ -127,14 +135,14 @@ static void kdc_recv_handler(struct kdc_socket *kdc_socket) return; } - blob = data_blob_talloc(kdc_socket, NULL, dsize); + blob = data_blob_talloc(tmp_ctx, NULL, dsize); if (blob.data == NULL) { /* hope this is a temporary low memory condition */ talloc_free(tmp_ctx); return; } - status = socket_recvfrom(kdc_socket->sock, blob.data, blob.length, &nread, 0, + status = socket_recvfrom(kdc_socket->sock, blob.data, blob.length, &nread, tmp_ctx, &src); if (!NT_STATUS_IS_OK(status)) { talloc_free(tmp_ctx); @@ -157,7 +165,8 @@ static void kdc_recv_handler(struct kdc_socket *kdc_socket) tmp_ctx, &blob, &reply, - src, my_addr); + src, my_addr, + 1 /* Datagram */); if (!ret) { talloc_free(tmp_ctx); return; @@ -240,7 +249,8 @@ static NTSTATUS kdc_tcp_recv(void *private, DATA_BLOB blob) &input, &reply, src_addr, - my_addr); + my_addr, + 0 /* Not datagram */); if (!ret) { talloc_free(tmp_ctx); return NT_STATUS_INTERNAL_ERROR; @@ -301,15 +311,19 @@ static void kdc_tcp_send(struct stream_connection *conn, uint16_t flags) calling conventions */ -static BOOL kdc_process(struct kdc_server *kdc, +static bool kdc_process(struct kdc_server *kdc, TALLOC_CTX *mem_ctx, DATA_BLOB *input, DATA_BLOB *reply, struct socket_address *peer_addr, - struct socket_address *my_addr) + struct socket_address *my_addr, + int datagram_reply) { int ret; krb5_data k5_reply; + krb5_data_zero(&k5_reply); + + krb5_kdc_update_time(NULL); DEBUG(10,("Received KDC packet of length %lu from %s:%d\n", (long)input->length - 4, peer_addr->addr, peer_addr->port)); @@ -319,14 +333,19 @@ static BOOL kdc_process(struct kdc_server *kdc, input->data, input->length, &k5_reply, peer_addr->addr, - peer_addr->sockaddr); + peer_addr->sockaddr, + datagram_reply); if (ret == -1) { *reply = data_blob(NULL, 0); - return False; + return false; } - *reply = data_blob_talloc(mem_ctx, k5_reply.data, k5_reply.length); - krb5_data_free(&k5_reply); - return True; + if (k5_reply.length) { + *reply = data_blob_talloc(mem_ctx, k5_reply.data, k5_reply.length); + krb5_free_data_contents(kdc->smb_krb5_context->krb5_context, &k5_reply); + } else { + *reply = data_blob(NULL, 0); + } + return true; } /* @@ -389,15 +408,14 @@ static const struct stream_server_ops kpasswdd_tcp_stream_ops = { /* start listening on the given address */ -static NTSTATUS kdc_add_socket(struct kdc_server *kdc, const char *address) +static NTSTATUS kdc_add_socket(struct kdc_server *kdc, const char *address, + uint16_t kdc_port, uint16_t kpasswd_port) { const struct model_ops *model_ops; struct kdc_socket *kdc_socket; struct kdc_socket *kpasswd_socket; struct socket_address *kdc_address, *kpasswd_address; NTSTATUS status; - uint16_t kdc_port = lp_krb5_port(); - uint16_t kpasswd_port = lp_kpasswd_port(); kdc_socket = talloc(kdc, struct kdc_socket); NT_STATUS_HAVE_NO_MEMORY(kdc_socket); @@ -498,7 +516,7 @@ static NTSTATUS kdc_add_socket(struct kdc_server *kdc, const char *address) /* setup our listening sockets on the configured network interfaces */ -static NTSTATUS kdc_startup_interfaces(struct kdc_server *kdc) +static NTSTATUS kdc_startup_interfaces(struct kdc_server *kdc, struct loadparm_context *lp_ctx) { int num_interfaces = iface_count(); TALLOC_CTX *tmp_ctx = talloc_new(kdc); @@ -508,7 +526,8 @@ static NTSTATUS kdc_startup_interfaces(struct kdc_server *kdc) for (i=0; ilp_ctx)) { case ROLE_STANDALONE: task_server_terminate(task, "kdc: no KDC required in standalone configuration"); return; case ROLE_DOMAIN_MEMBER: task_server_terminate(task, "kdc: no KDC required in member server configuration"); return; - case ROLE_DOMAIN_PDC: - case ROLE_DOMAIN_BDC: + case ROLE_DOMAIN_CONTROLLER: /* Yes, we want a KDC */ break; } @@ -554,17 +582,9 @@ static void kdc_task_init(struct task_server *task) kdc->task = task; - /* Setup the KDC configuration */ - kdc->config = talloc(kdc, krb5_kdc_configuration); - if (!kdc->config) { - task_server_terminate(task, "kdc: out of memory"); - return; - } - krb5_kdc_default_config(kdc->config); - initialize_krb5_error_table(); - ret = smb_krb5_init_context(kdc, &kdc->smb_krb5_context); + ret = smb_krb5_init_context(kdc, task->event_ctx, task->lp_ctx, &kdc->smb_krb5_context); if (ret) { DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n", error_message(ret))); @@ -574,8 +594,15 @@ static void kdc_task_init(struct task_server *task) krb5_add_et_list(kdc->smb_krb5_context->krb5_context, initialize_hdb_error_table_r); + ret = krb5_kdc_get_config(kdc->smb_krb5_context->krb5_context, + &kdc->config); + if(ret) { + task_server_terminate(task, "kdc: failed to get KDC configuration"); + return; + } + kdc->config->logf = kdc->smb_krb5_context->logf; - kdc->config->db = talloc(kdc->config, struct HDB *); + kdc->config->db = talloc(kdc, struct HDB *); if (!kdc->config->db) { task_server_terminate(task, "kdc: out of memory"); return; @@ -594,8 +621,22 @@ static void kdc_task_init(struct task_server *task) task_server_terminate(task, "kdc: failed to register hdb keytab"); return; } + + /* Registar WinDC hooks */ + ret = _krb5_plugin_register(kdc->smb_krb5_context->krb5_context, + PLUGIN_TYPE_DATA, "windc", + &windc_plugin_table); + if(ret) { + task_server_terminate(task, "kdc: failed to register hdb keytab"); + return; + } + + krb5_kdc_windc_init(kdc->smb_krb5_context->krb5_context); + + kdc_mem_ctx = kdc->smb_krb5_context; + /* start listening on the configured network interfaces */ - status = kdc_startup_interfaces(kdc); + status = kdc_startup_interfaces(kdc, task->lp_ctx); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "kdc failed to setup interfaces"); return;