s3: rpc_client: Allocate struct db_context * off the local frame, as all other variab...
[Samba.git] / source4 / kdc / kdc-service-mit.c
blob7febf158a01ed86659dd4d9773469a2613b8567e
1 /*
2 Unix SMB/CIFS implementation.
4 Start MIT krb5kdc server within Samba AD
6 Copyright (c) 2014-2016 Andreas Schneider <asn@samba.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "talloc.h"
24 #include "tevent.h"
25 #include "system/filesys.h"
26 #include "lib/param/param.h"
27 #include "lib/util/samba_util.h"
28 #include "source4/smbd/service.h"
29 #include "source4/smbd/process_model.h"
30 #include "kdc/kdc-service-mit.h"
31 #include "dynconfig.h"
32 #include "libds/common/roles.h"
33 #include "lib/socket/netif.h"
34 #include "samba/session.h"
35 #include "dsdb/samdb/samdb.h"
36 #include "kdc/samba_kdc.h"
37 #include "kdc/kdc-server.h"
38 #include "kdc/kpasswd-service.h"
39 #include <kadm5/admin.h>
40 #include <kdb.h>
42 #include "source4/kdc/mit_kdc_irpc.h"
44 /* PROTOTYPES */
45 static void mitkdc_server_done(struct tevent_req *subreq);
47 static int kdc_server_destroy(struct kdc_server *kdc)
49 if (kdc->private_data != NULL) {
50 kadm5_destroy(kdc->private_data);
53 return 0;
56 static NTSTATUS startup_kpasswd_server(TALLOC_CTX *mem_ctx,
57 struct kdc_server *kdc,
58 struct loadparm_context *lp_ctx,
59 struct interface *ifaces)
61 const struct model_ops *model_ops;
62 int num_interfaces;
63 int i;
64 TALLOC_CTX *tmp_ctx;
65 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
66 uint16_t kpasswd_port;
67 bool done_wildcard = false;
68 bool ok;
70 kpasswd_port = lpcfg_kpasswd_port(lp_ctx);
71 if (kpasswd_port == 0) {
72 return NT_STATUS_OK;
75 model_ops = process_model_startup("single");
76 if (model_ops == NULL) {
77 DBG_ERR("Can't find 'single' process model_ops\n");
78 return NT_STATUS_INTERNAL_ERROR;
81 tmp_ctx = talloc_named_const(mem_ctx, 0, "kpasswd");
82 if (tmp_ctx == NULL) {
83 return NT_STATUS_NO_MEMORY;
86 num_interfaces = iface_list_count(ifaces);
88 ok = lpcfg_bind_interfaces_only(lp_ctx);
89 if (!ok) {
90 int num_binds = 0;
91 char **wcard;
93 wcard = iface_list_wildcard(tmp_ctx);
94 if (wcard == NULL) {
95 status = NT_STATUS_NO_MEMORY;
96 goto out;
99 for (i = 0; wcard[i] != NULL; i++) {
100 status = kdc_add_socket(kdc,
101 model_ops,
102 "kpasswd",
103 wcard[i],
104 kpasswd_port,
105 kpasswd_process,
106 false);
107 if (NT_STATUS_IS_OK(status)) {
108 num_binds++;
111 talloc_free(wcard);
113 if (num_binds == 0) {
114 status = NT_STATUS_INVALID_PARAMETER_MIX;
115 goto out;
118 done_wildcard = true;
121 for (i = 0; i < num_interfaces; i++) {
122 const char *address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
124 status = kdc_add_socket(kdc,
125 model_ops,
126 "kpasswd",
127 address,
128 kpasswd_port,
129 kpasswd_process,
130 done_wildcard);
131 if (NT_STATUS_IS_OK(status)) {
132 goto out;
136 out:
137 talloc_free(tmp_ctx);
138 return status;
142 * Startup a copy of the krb5kdc as a child daemon
144 void mitkdc_task_init(struct task_server *task)
146 struct tevent_req *subreq;
147 const char * const *kdc_cmd;
148 struct interface *ifaces;
149 char *kdc_config = NULL;
150 struct kdc_server *kdc;
151 krb5_error_code code;
152 NTSTATUS status;
153 kadm5_ret_t ret;
154 kadm5_config_params config;
155 void *server_handle;
157 task_server_set_title(task, "task[mitkdc_parent]");
159 switch (lpcfg_server_role(task->lp_ctx)) {
160 case ROLE_STANDALONE:
161 task_server_terminate(task,
162 "The KDC is not required in standalone "
163 "server configuration, terminate!",
164 false);
165 return;
166 case ROLE_DOMAIN_MEMBER:
167 task_server_terminate(task,
168 "The KDC is not required in member "
169 "server configuration",
170 false);
171 return;
172 case ROLE_ACTIVE_DIRECTORY_DC:
173 /* Yes, we want to start the KDC */
174 break;
177 /* Load interfaces for kpasswd */
178 load_interface_list(task, task->lp_ctx, &ifaces);
179 if (iface_list_count(ifaces) == 0) {
180 task_server_terminate(task,
181 "KDC: no network interfaces configured",
182 false);
183 return;
186 kdc_config = talloc_asprintf(task,
187 "%s/kdc.conf",
188 lpcfg_private_dir(task->lp_ctx));
189 if (kdc_config == NULL) {
190 task_server_terminate(task,
191 "KDC: no memory",
192 false);
193 return;
195 setenv("KRB5_KDC_PROFILE", kdc_config, 0);
196 TALLOC_FREE(kdc_config);
198 /* start it as a child process */
199 kdc_cmd = lpcfg_mit_kdc_command(task->lp_ctx);
201 subreq = samba_runcmd_send(task,
202 task->event_ctx,
203 timeval_zero(),
204 1, /* stdout log level */
205 0, /* stderr log level */
206 kdc_cmd,
207 "-n", /* Don't go into background */
208 #if 0
209 "-w 2", /* Start two workers */
210 #endif
211 NULL);
212 if (subreq == NULL) {
213 DEBUG(0, ("Failed to start MIT KDC as child daemon\n"));
215 task_server_terminate(task,
216 "Failed to startup mitkdc task",
217 true);
218 return;
221 tevent_req_set_callback(subreq, mitkdc_server_done, task);
223 DEBUG(5,("Started krb5kdc process\n"));
225 status = samba_setup_mit_kdc_irpc(task);
226 if (!NT_STATUS_IS_OK(status)) {
227 task_server_terminate(task,
228 "Failed to setup kdc irpc service",
229 true);
232 DEBUG(5,("Started irpc service for kdc_server\n"));
234 kdc = talloc_zero(task, struct kdc_server);
235 if (kdc == NULL) {
236 task_server_terminate(task, "KDC: Out of memory", true);
237 return;
239 talloc_set_destructor(kdc, kdc_server_destroy);
241 kdc->task = task;
243 kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context);
244 if (kdc->base_ctx == NULL) {
245 task_server_terminate(task, "KDC: Out of memory", true);
246 return;
249 kdc->base_ctx->ev_ctx = task->event_ctx;
250 kdc->base_ctx->lp_ctx = task->lp_ctx;
252 initialize_krb5_error_table();
254 code = smb_krb5_init_context(kdc,
255 kdc->task->lp_ctx,
256 &kdc->smb_krb5_context);
257 if (code != 0) {
258 task_server_terminate(task,
259 "KDC: Unable to initialized krb5 context",
260 true);
261 return;
264 code = kadm5_init_krb5_context(&kdc->smb_krb5_context->krb5_context);
265 if (code != 0) {
266 task_server_terminate(task,
267 "KDC: Unable to init kadm5 krb5_context",
268 true);
269 return;
272 ZERO_STRUCT(config);
273 config.mask = KADM5_CONFIG_REALM;
274 config.realm = discard_const_p(char, lpcfg_realm(kdc->task->lp_ctx));
276 ret = kadm5_init(kdc->smb_krb5_context->krb5_context,
277 discard_const_p(char, "kpasswd"),
278 NULL, /* pass */
279 discard_const_p(char, "kpasswd"),
280 &config,
281 KADM5_STRUCT_VERSION,
282 KADM5_API_VERSION_4,
283 NULL,
284 &server_handle);
285 if (ret != 0) {
286 task_server_terminate(task,
287 "KDC: Initialize kadm5",
288 true);
289 return;
291 kdc->private_data = server_handle;
293 code = krb5_db_register_keytab(kdc->smb_krb5_context->krb5_context);
294 if (code != 0) {
295 task_server_terminate(task,
296 "KDC: Unable to KDB",
297 true);
298 return;
301 kdc->keytab_name = talloc_asprintf(kdc, "KDB:");
302 if (kdc->keytab_name == NULL) {
303 task_server_terminate(task,
304 "KDC: Out of memory",
305 true);
306 return;
309 kdc->samdb = samdb_connect(kdc,
310 kdc->task->event_ctx,
311 kdc->task->lp_ctx,
312 system_session(kdc->task->lp_ctx),
314 if (kdc->samdb == NULL) {
315 task_server_terminate(task,
316 "KDC: Unable to connect to sambdb",
317 true);
318 return;
321 status = startup_kpasswd_server(kdc,
322 kdc,
323 task->lp_ctx,
324 ifaces);
325 if (!NT_STATUS_IS_OK(status)) {
326 task_server_terminate(task,
327 "KDC: Unable to start kpasswd server",
328 true);
331 DEBUG(5,("Started kpasswd service for kdc_server\n"));
335 * This gets called the kdc exits.
337 static void mitkdc_server_done(struct tevent_req *subreq)
339 struct task_server *task =
340 tevent_req_callback_data(subreq,
341 struct task_server);
342 int sys_errno;
343 int ret;
345 ret = samba_runcmd_recv(subreq, &sys_errno);
346 if (ret != 0) {
347 DEBUG(0, ("The MIT KDC daemon died with exit status %d\n",
348 sys_errno));
349 } else {
350 DEBUG(0,("The MIT KDC daemon exited normally\n"));
353 task_server_terminate(task, "mitkdc child process exited", true);
356 /* Called at MIT KRB5 startup - register ourselves as a server service */
357 NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx);
359 NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx)
361 return register_server_service(mem_ctx, "kdc", mitkdc_task_init);