5d111ee82d23674889b607afdf5d1b78e50491ba
[amitay/samba.git] / source4 / kdc / kdc-service-mit.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Start MIT krb5kdc server within Samba AD
5
6    Copyright (c) 2014-2016 Andreas Schneider <asn@samba.org>
7
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.
12
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.
17
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/>.
20 */
21
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>
41
42 #include "source4/kdc/mit_kdc_irpc.h"
43
44 /* PROTOTYPES */
45 static void mitkdc_server_done(struct tevent_req *subreq);
46
47 static int kdc_server_destroy(struct kdc_server *kdc)
48 {
49         if (kdc->private_data != NULL) {
50                 kadm5_destroy(kdc->private_data);
51         }
52
53         return 0;
54 }
55
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)
60 {
61         int num_interfaces;
62         int i;
63         TALLOC_CTX *tmp_ctx;
64         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
65         uint16_t kpasswd_port;
66         bool done_wildcard = false;
67         bool ok;
68
69         kpasswd_port = lpcfg_kpasswd_port(lp_ctx);
70         if (kpasswd_port == 0) {
71                 return NT_STATUS_OK;
72         }
73
74         tmp_ctx = talloc_named_const(mem_ctx, 0, "kpasswd");
75         if (tmp_ctx == NULL) {
76                 return NT_STATUS_NO_MEMORY;
77         }
78
79         num_interfaces = iface_list_count(ifaces);
80
81         ok = lpcfg_bind_interfaces_only(lp_ctx);
82         if (!ok) {
83                 int num_binds = 0;
84                 char **wcard;
85
86                 wcard = iface_list_wildcard(tmp_ctx);
87                 if (wcard == NULL) {
88                         status = NT_STATUS_NO_MEMORY;
89                         goto out;
90                 }
91
92                 for (i = 0; wcard[i] != NULL; i++) {
93                         status = kdc_add_socket(kdc,
94                                                 kdc->task->model_ops,
95                                                 "kpasswd",
96                                                 wcard[i],
97                                                 kpasswd_port,
98                                                 kpasswd_process,
99                                                 false);
100                         if (NT_STATUS_IS_OK(status)) {
101                                 num_binds++;
102                         }
103                 }
104                 talloc_free(wcard);
105
106                 if (num_binds == 0) {
107                         status = NT_STATUS_INVALID_PARAMETER_MIX;
108                         goto out;
109                 }
110
111                 done_wildcard = true;
112         }
113
114         for (i = 0; i < num_interfaces; i++) {
115                 const char *address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
116
117                 status = kdc_add_socket(kdc,
118                                         kdc->task->model_ops,
119                                         "kpasswd",
120                                         address,
121                                         kpasswd_port,
122                                         kpasswd_process,
123                                         done_wildcard);
124                 if (NT_STATUS_IS_OK(status)) {
125                         goto out;
126                 }
127         }
128
129 out:
130         talloc_free(tmp_ctx);
131         return status;
132 }
133
134 /*
135  * Startup a copy of the krb5kdc as a child daemon
136  */
137 void mitkdc_task_init(struct task_server *task)
138 {
139         struct tevent_req *subreq;
140         const char * const *kdc_cmd;
141         struct interface *ifaces;
142         char *kdc_config = NULL;
143         struct kdc_server *kdc;
144         krb5_error_code code;
145         NTSTATUS status;
146         kadm5_ret_t ret;
147         kadm5_config_params config;
148         void *server_handle;
149
150         task_server_set_title(task, "task[mitkdc_parent]");
151
152         switch (lpcfg_server_role(task->lp_ctx)) {
153         case ROLE_STANDALONE:
154                 task_server_terminate(task,
155                                       "The KDC is not required in standalone "
156                                       "server configuration, terminate!",
157                                       false);
158                 return;
159         case ROLE_DOMAIN_MEMBER:
160                 task_server_terminate(task,
161                                       "The KDC is not required in member "
162                                       "server configuration",
163                                       false);
164                 return;
165         case ROLE_ACTIVE_DIRECTORY_DC:
166                 /* Yes, we want to start the KDC */
167                 break;
168         }
169
170         /* Load interfaces for kpasswd */
171         load_interface_list(task, task->lp_ctx, &ifaces);
172         if (iface_list_count(ifaces) == 0) {
173                 task_server_terminate(task,
174                                       "KDC: no network interfaces configured",
175                                       false);
176                 return;
177         }
178
179         kdc_config = talloc_asprintf(task,
180                                      "%s/kdc.conf",
181                                      lpcfg_private_dir(task->lp_ctx));
182         if (kdc_config == NULL) {
183                 task_server_terminate(task,
184                                       "KDC: no memory",
185                                       false);
186                 return;
187         }
188         setenv("KRB5_KDC_PROFILE", kdc_config, 0);
189         TALLOC_FREE(kdc_config);
190
191         /* start it as a child process */
192         kdc_cmd = lpcfg_mit_kdc_command(task->lp_ctx);
193
194         subreq = samba_runcmd_send(task,
195                                    task->event_ctx,
196                                    timeval_zero(),
197                                    1, /* stdout log level */
198                                    0, /* stderr log level */
199                                    kdc_cmd,
200                                    "-n", /* Don't go into background */
201 #if 0
202                                    "-w 2", /* Start two workers */
203 #endif
204                                    NULL);
205         if (subreq == NULL) {
206                 DEBUG(0, ("Failed to start MIT KDC as child daemon\n"));
207
208                 task_server_terminate(task,
209                                       "Failed to startup mitkdc task",
210                                       true);
211                 return;
212         }
213
214         tevent_req_set_callback(subreq, mitkdc_server_done, task);
215
216         DEBUG(5,("Started krb5kdc process\n"));
217
218         status = samba_setup_mit_kdc_irpc(task);
219         if (!NT_STATUS_IS_OK(status)) {
220                 task_server_terminate(task,
221                                       "Failed to setup kdc irpc service",
222                                       true);
223         }
224
225         DEBUG(5,("Started irpc service for kdc_server\n"));
226
227         kdc = talloc_zero(task, struct kdc_server);
228         if (kdc == NULL) {
229                 task_server_terminate(task, "KDC: Out of memory", true);
230                 return;
231         }
232         talloc_set_destructor(kdc, kdc_server_destroy);
233
234         kdc->task = task;
235
236         kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context);
237         if (kdc->base_ctx == NULL) {
238                 task_server_terminate(task, "KDC: Out of memory", true);
239                 return;
240         }
241
242         kdc->base_ctx->ev_ctx = task->event_ctx;
243         kdc->base_ctx->lp_ctx = task->lp_ctx;
244
245         initialize_krb5_error_table();
246
247         code = smb_krb5_init_context(kdc,
248                                      kdc->task->lp_ctx,
249                                      &kdc->smb_krb5_context);
250         if (code != 0) {
251                 task_server_terminate(task,
252                                       "KDC: Unable to initialized krb5 context",
253                                       true);
254                 return;
255         }
256
257         code = kadm5_init_krb5_context(&kdc->smb_krb5_context->krb5_context);
258         if (code != 0) {
259                 task_server_terminate(task,
260                                       "KDC: Unable to init kadm5 krb5_context",
261                                       true);
262                 return;
263         }
264
265         ZERO_STRUCT(config);
266         config.mask = KADM5_CONFIG_REALM;
267         config.realm = discard_const_p(char, lpcfg_realm(kdc->task->lp_ctx));
268
269         ret = kadm5_init(kdc->smb_krb5_context->krb5_context,
270                          discard_const_p(char, "kpasswd"),
271                          NULL, /* pass */
272                          discard_const_p(char, "kpasswd"),
273                          &config,
274                          KADM5_STRUCT_VERSION,
275                          KADM5_API_VERSION_4,
276                          NULL,
277                          &server_handle);
278         if (ret != 0) {
279                 task_server_terminate(task,
280                                       "KDC: Initialize kadm5",
281                                       true);
282                 return;
283         }
284         kdc->private_data = server_handle;
285
286         code = krb5_db_register_keytab(kdc->smb_krb5_context->krb5_context);
287         if (code != 0) {
288                 task_server_terminate(task,
289                                       "KDC: Unable to KDB",
290                                       true);
291                 return;
292         }
293
294         kdc->keytab_name = talloc_asprintf(kdc, "KDB:");
295         if (kdc->keytab_name == NULL) {
296                 task_server_terminate(task,
297                                       "KDC: Out of memory",
298                                       true);
299                 return;
300         }
301
302         kdc->samdb = samdb_connect(kdc,
303                                    kdc->task->event_ctx,
304                                    kdc->task->lp_ctx,
305                                    system_session(kdc->task->lp_ctx),
306                                    NULL,
307                                    0);
308         if (kdc->samdb == NULL) {
309                 task_server_terminate(task,
310                                       "KDC: Unable to connect to sambdb",
311                                       true);
312                 return;
313         }
314
315         status = startup_kpasswd_server(kdc,
316                                     kdc,
317                                     task->lp_ctx,
318                                     ifaces);
319         if (!NT_STATUS_IS_OK(status)) {
320                 task_server_terminate(task,
321                                       "KDC: Unable to start kpasswd server",
322                                       true);
323         }
324
325         DEBUG(5,("Started kpasswd service for kdc_server\n"));
326 }
327
328 /*
329  * This gets called the kdc exits.
330  */
331 static void mitkdc_server_done(struct tevent_req *subreq)
332 {
333         struct task_server *task =
334                 tevent_req_callback_data(subreq,
335                 struct task_server);
336         int sys_errno;
337         int ret;
338
339         ret = samba_runcmd_recv(subreq, &sys_errno);
340         if (ret != 0) {
341                 DEBUG(0, ("The MIT KDC daemon died with exit status %d\n",
342                           sys_errno));
343         } else {
344                 DEBUG(0,("The MIT KDC daemon exited normally\n"));
345         }
346
347         task_server_terminate(task, "mitkdc child process exited", true);
348 }
349
350 /* Called at MIT KRB5 startup - register ourselves as a server service */
351 NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx);
352
353 NTSTATUS server_service_mitkdc_init(TALLOC_CTX *mem_ctx)
354 {
355         static const struct service_details details = {
356                 .inhibit_fork_on_accept = true,
357                 /* 
358                  * Need to prevent pre-forking on kdc.
359                  * The task_init function is run on the master process only
360                  * and the irpc process name is registered in it's event loop.
361                  * The child worker processes initialise their event loops on
362                  * fork, so are not listening for the irpc event.
363                  *
364                  * The master process does not wait on that event context
365                  * the master process is responsible for managing the worker
366                  * processes not performing work.
367                  */
368                 .inhibit_pre_fork = true
369         };
370         return register_server_service(mem_ctx, "kdc", mitkdc_task_init,
371                                        &details);
372 }