Line data Source code
1 : /*
2 : SSSD
3 :
4 : IPA Subdomains Module - server mode
5 :
6 : Authors:
7 : Sumit Bose <sbose@redhat.com>
8 :
9 : Copyright (C) 2015 Red Hat
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "providers/ldap/sdap_async.h"
26 : #include "providers/ldap/sdap_idmap.h"
27 : #include "providers/ipa/ipa_subdomains.h"
28 : #include "providers/ipa/ipa_common.h"
29 : #include "providers/ipa/ipa_id.h"
30 :
31 : /* These constants are defined in MS-ADTS 6.1.6.7.1
32 : * https://msdn.microsoft.com/en-us/library/cc223768.aspx
33 : */
34 : #define LSA_TRUST_DIRECTION_INBOUND 0x00000001
35 : #define LSA_TRUST_DIRECTION_OUTBOUND 0x00000002
36 :
37 0 : static char *forest_keytab(TALLOC_CTX *mem_ctx, const char *forest)
38 : {
39 0 : return talloc_asprintf(mem_ctx,
40 : "%s/%s.keytab", IPA_TRUST_KEYTAB_DIR, forest);
41 : }
42 :
43 0 : static char *subdomain_trust_princ(TALLOC_CTX *mem_ctx,
44 : const char *forest_realm,
45 : struct sss_domain_info *sd)
46 : {
47 0 : if (sd->parent->flat_name == NULL) {
48 0 : DEBUG(SSSDBG_CRIT_FAILURE,
49 : "Unknown flat name for parent %s\n", sd->parent->name);
50 0 : return NULL;
51 : }
52 :
53 0 : return talloc_asprintf(mem_ctx, "%s$@%s",
54 0 : sd->parent->flat_name, forest_realm);
55 : }
56 :
57 2 : static uint32_t default_direction(TALLOC_CTX *mem_ctx,
58 : struct ldb_context *ldb_ctx,
59 : struct sysdb_attrs *attrs)
60 : {
61 2 : struct ldb_dn *dn = NULL;
62 : uint32_t direction;
63 :
64 2 : dn = ipa_subdom_ldb_dn(mem_ctx, ldb_ctx, attrs);
65 2 : if (dn == NULL) {
66 : /* Shouldn't happen, but let's try system keytab in this case */
67 0 : DEBUG(SSSDBG_CRIT_FAILURE,
68 : "Cannot determine subdomain DN, falling back to two-way trust\n");
69 0 : return (LSA_TRUST_DIRECTION_INBOUND|LSA_TRUST_DIRECTION_OUTBOUND);
70 : }
71 :
72 2 : if (ipa_subdom_is_member_dom(dn) == true) {
73 : /* It's expected member domains do not have the direction */
74 1 : direction = 0;
75 : } else {
76 : /* Old server? Default to 2way trust */
77 1 : direction = (LSA_TRUST_DIRECTION_INBOUND|LSA_TRUST_DIRECTION_OUTBOUND);
78 : }
79 :
80 2 : talloc_free(dn);
81 2 : return direction;
82 : }
83 :
84 5 : errno_t ipa_server_get_trust_direction(struct sysdb_attrs *sd,
85 : struct ldb_context *ldb_ctx,
86 : uint32_t *_direction)
87 : {
88 5 : uint32_t ipa_trust_direction = 0;
89 : uint32_t direction;
90 : int ret;
91 :
92 5 : ret = sysdb_attrs_get_uint32_t(sd, IPA_TRUST_DIRECTION,
93 : &ipa_trust_direction);
94 5 : DEBUG(SSSDBG_TRACE_INTERNAL,
95 : "Raw %s value: %d\n", IPA_TRUST_DIRECTION, ipa_trust_direction);
96 5 : if (ret == ENOENT) {
97 2 : direction = default_direction(sd, ldb_ctx, sd);
98 3 : } else if (ret == EOK) {
99 : /* Just store the AD value in SYSDB, we will check it while we're
100 : * trying to use the trust */
101 3 : direction = ipa_trust_direction;
102 : } else {
103 0 : return ret;
104 : }
105 :
106 5 : *_direction = direction;
107 5 : return EOK;
108 : }
109 :
110 4 : const char *ipa_trust_dir2str(uint32_t direction)
111 : {
112 4 : if ((direction & LSA_TRUST_DIRECTION_OUTBOUND)
113 1 : && (direction & LSA_TRUST_DIRECTION_INBOUND)) {
114 0 : return "two-way trust";
115 4 : } else if (direction & LSA_TRUST_DIRECTION_OUTBOUND) {
116 1 : return "one-way outbound: local domain is trusted by remote domain";
117 3 : } else if (direction & LSA_TRUST_DIRECTION_INBOUND) {
118 1 : return "one-way inbound: local domain trusts the remote domain";
119 2 : } else if (direction == 0) {
120 1 : return "trust direction not set";
121 : }
122 :
123 1 : return "unknown";
124 : }
125 :
126 : #ifndef IPA_GETKEYTAB_TIMEOUT
127 : #define IPA_GETKEYTAB_TIMEOUT 5
128 : #endif /* IPA_GETKEYTAB_TIMEOUT */
129 :
130 : static struct ad_options *
131 0 : ipa_create_1way_trust_ctx(struct ipa_id_ctx *id_ctx,
132 : const char *forest,
133 : const char *forest_realm,
134 : struct sss_domain_info *subdom)
135 : {
136 : char *keytab;
137 : char *principal;
138 : struct ad_options *ad_options;
139 : const char *ad_domain;
140 :
141 0 : ad_domain = subdom->name;
142 0 : keytab = forest_keytab(id_ctx, forest);
143 0 : principal = subdomain_trust_princ(id_ctx, forest_realm, subdom);
144 0 : if (keytab == NULL || principal == NULL) {
145 0 : return NULL;
146 : }
147 :
148 0 : ad_options = ad_create_1way_trust_options(id_ctx,
149 : ad_domain,
150 0 : id_ctx->server_mode->hostname,
151 : keytab,
152 : principal);
153 0 : if (ad_options == NULL) {
154 0 : talloc_free(keytab);
155 0 : talloc_free(principal);
156 0 : return NULL;
157 : }
158 :
159 0 : return ad_options;
160 : }
161 :
162 0 : static struct ad_options *ipa_ad_options_new(struct ipa_id_ctx *id_ctx,
163 : struct sss_domain_info *subdom)
164 : {
165 0 : struct ad_options *ad_options = NULL;
166 : uint32_t direction;
167 : const char *forest;
168 : const char *forest_realm;
169 :
170 : /* Trusts are only established with forest roots */
171 0 : direction = subdom->forest_root->trust_direction;
172 0 : forest_realm = subdom->forest_root->realm;
173 0 : forest = subdom->forest_root->forest;
174 :
175 0 : if (direction & LSA_TRUST_DIRECTION_OUTBOUND) {
176 0 : ad_options = ad_create_2way_trust_options(id_ctx,
177 0 : id_ctx->server_mode->realm,
178 0 : subdom->name,
179 0 : id_ctx->server_mode->hostname,
180 : NULL);
181 0 : } else if (direction & LSA_TRUST_DIRECTION_INBOUND) {
182 0 : ad_options = ipa_create_1way_trust_ctx(id_ctx, forest,
183 : forest_realm, subdom);
184 : } else {
185 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported trust direction!\n");
186 0 : ad_options = NULL;
187 : }
188 :
189 0 : if (ad_options == NULL) {
190 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD options\n");
191 0 : return NULL;
192 : }
193 0 : return ad_options;
194 : }
195 :
196 :
197 : static errno_t
198 0 : ipa_ad_ctx_new(struct be_ctx *be_ctx,
199 : struct ipa_id_ctx *id_ctx,
200 : struct sss_domain_info *subdom,
201 : struct ad_id_ctx **_ad_id_ctx)
202 : {
203 : struct ad_options *ad_options;
204 : struct ad_id_ctx *ad_id_ctx;
205 : const char *gc_service_name;
206 : struct ad_srv_plugin_ctx *srv_ctx;
207 : const char *ad_domain;
208 : const char *ad_site_override;
209 : struct sdap_domain *sdom;
210 : errno_t ret;
211 : const char *extra_attrs;
212 :
213 0 : ad_domain = subdom->name;
214 0 : DEBUG(SSSDBG_TRACE_LIBS, "Setting up AD subdomain %s\n", subdom->name);
215 :
216 0 : ad_options = ipa_ad_options_new(id_ctx, subdom);
217 0 : if (ad_options == NULL) {
218 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD options\n");
219 0 : talloc_free(ad_options);
220 0 : return ENOMEM;
221 : }
222 :
223 0 : extra_attrs = dp_opt_get_string(id_ctx->sdap_id_ctx->opts->basic,
224 : SDAP_USER_EXTRA_ATTRS);
225 0 : if (extra_attrs != NULL) {
226 0 : DEBUG(SSSDBG_TRACE_ALL,
227 : "Setting extra attrs for subdomain [%s] to [%s].\n", ad_domain,
228 : extra_attrs);
229 :
230 0 : ret = dp_opt_set_string(ad_options->id->basic, SDAP_USER_EXTRA_ATTRS,
231 : extra_attrs);
232 0 : if (ret != EOK) {
233 0 : DEBUG(SSSDBG_OP_FAILURE, "dp_opt_get_string failed.\n");
234 0 : talloc_free(ad_options);
235 0 : return ret;
236 : }
237 :
238 0 : ret = sdap_extend_map_with_list(ad_options->id, ad_options->id,
239 : SDAP_USER_EXTRA_ATTRS,
240 0 : ad_options->id->user_map,
241 : SDAP_OPTS_USER,
242 0 : &ad_options->id->user_map,
243 0 : &ad_options->id->user_map_cnt);
244 0 : if (ret != EOK) {
245 0 : DEBUG(SSSDBG_OP_FAILURE, "sdap_extend_map_with_list failed.\n");
246 0 : talloc_free(ad_options);
247 0 : return ret;
248 : }
249 : } else {
250 0 : DEBUG(SSSDBG_TRACE_ALL, "No extra attrs set.\n");
251 : }
252 :
253 0 : gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->forest);
254 0 : if (gc_service_name == NULL) {
255 0 : talloc_free(ad_options);
256 0 : return ENOMEM;
257 : }
258 :
259 : /* Set KRB5 realm to same as the one of IPA when IPA
260 : * is able to attach PAC. For testing, use hardcoded. */
261 0 : ret = ad_failover_init(ad_options, be_ctx, NULL, NULL,
262 0 : id_ctx->server_mode->realm,
263 0 : subdom->name, gc_service_name,
264 0 : subdom->name, &ad_options->service);
265 0 : if (ret != EOK) {
266 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD failover\n");
267 0 : talloc_free(ad_options);
268 0 : return ret;
269 : }
270 :
271 0 : ad_id_ctx = ad_id_ctx_init(ad_options, be_ctx);
272 0 : if (ad_id_ctx == NULL) {
273 0 : talloc_free(ad_options);
274 0 : return ENOMEM;
275 : }
276 0 : ad_id_ctx->sdap_id_ctx->opts = ad_options->id;
277 0 : ad_options->id_ctx = ad_id_ctx;
278 :
279 0 : ad_site_override = dp_opt_get_string(ad_options->basic, AD_SITE);
280 :
281 : /* use AD plugin */
282 0 : srv_ctx = ad_srv_plugin_ctx_init(be_ctx, be_ctx->be_res,
283 : default_host_dbs,
284 0 : ad_id_ctx->ad_options->id,
285 0 : id_ctx->server_mode->hostname,
286 : ad_domain,
287 : ad_site_override);
288 0 : if (srv_ctx == NULL) {
289 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
290 0 : return ENOMEM;
291 : }
292 0 : be_fo_set_srv_lookup_plugin(be_ctx, ad_srv_plugin_send,
293 : ad_srv_plugin_recv, srv_ctx, "AD");
294 :
295 0 : ret = sdap_domain_subdom_add(ad_id_ctx->sdap_id_ctx,
296 0 : ad_id_ctx->sdap_id_ctx->opts->sdom,
297 : subdom->parent);
298 0 : if (ret != EOK) {
299 0 : DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize sdap domain\n");
300 0 : talloc_free(ad_options);
301 0 : return ret;
302 : }
303 :
304 0 : sdom = sdap_domain_get(ad_id_ctx->sdap_id_ctx->opts, subdom);
305 0 : if (sdom == NULL) {
306 0 : return EFAULT;
307 : }
308 :
309 0 : sdap_inherit_options(subdom->parent->sd_inherit,
310 0 : id_ctx->sdap_id_ctx->opts,
311 0 : ad_id_ctx->sdap_id_ctx->opts);
312 :
313 0 : ret = sdap_id_setup_tasks(be_ctx,
314 : ad_id_ctx->sdap_id_ctx,
315 : sdom,
316 : ldap_enumeration_send,
317 : ldap_enumeration_recv,
318 0 : ad_id_ctx->sdap_id_ctx);
319 0 : if (ret != EOK) {
320 0 : talloc_free(ad_options);
321 0 : return ret;
322 : }
323 :
324 0 : sdom->pvt = ad_id_ctx;
325 :
326 : /* Set up the ID mapping object */
327 0 : ad_id_ctx->sdap_id_ctx->opts->idmap_ctx =
328 0 : id_ctx->sdap_id_ctx->opts->idmap_ctx;
329 :
330 0 : *_ad_id_ctx = ad_id_ctx;
331 0 : return EOK;
332 : }
333 :
334 : struct ipa_getkeytab_state {
335 : int child_status;
336 : struct sss_child_ctx_old *child_ctx;
337 : struct tevent_timer *timeout_handler;
338 : };
339 :
340 : static void ipa_getkeytab_exec(const char *ccache,
341 : const char *server,
342 : const char *principal,
343 : const char *keytab_path);
344 : static void ipa_getkeytab_done(int child_status,
345 : struct tevent_signal *sige,
346 : void *pvt);
347 : static void ipa_getkeytab_timeout(struct tevent_context *ev,
348 : struct tevent_timer *te,
349 : struct timeval tv, void *pvt);
350 :
351 0 : static struct tevent_req *ipa_getkeytab_send(TALLOC_CTX *mem_ctx,
352 : struct tevent_context *ev,
353 : const char *ccache,
354 : const char *server,
355 : const char *principal,
356 : const char *keytab)
357 :
358 :
359 : {
360 : errno_t ret;
361 0 : struct tevent_req *req = NULL;
362 : struct ipa_getkeytab_state *state;
363 : pid_t child_pid;
364 : struct timeval tv;
365 :
366 0 : req = tevent_req_create(mem_ctx, &state, struct ipa_getkeytab_state);
367 0 : if (req == NULL) {
368 0 : return NULL;
369 : }
370 0 : state->child_status = EFAULT;
371 :
372 0 : if (server == NULL || principal == NULL || keytab == NULL) {
373 0 : ret = EINVAL;
374 0 : goto done;
375 : }
376 :
377 0 : DEBUG(SSSDBG_TRACE_FUNC,
378 : "Retrieving keytab for %s from %s into %s using ccache %s\n",
379 : principal, server, keytab, ccache);
380 :
381 0 : child_pid = fork();
382 0 : if (child_pid == 0) { /* child */
383 0 : ipa_getkeytab_exec(ccache, server, principal, keytab);
384 0 : } else if (child_pid > 0) { /* parent */
385 : /* Set up SIGCHLD handler */
386 0 : ret = child_handler_setup(ev, child_pid, ipa_getkeytab_done, req,
387 0 : &state->child_ctx);
388 0 : if (ret != EOK) {
389 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not set up child handlers [%d]: %s\n",
390 : ret, sss_strerror(ret));
391 0 : ret = ERR_IPA_GETKEYTAB_FAILED;
392 0 : goto done;
393 : }
394 :
395 : /* Set up timeout handler */
396 0 : tv = tevent_timeval_current_ofs(IPA_GETKEYTAB_TIMEOUT, 0);
397 0 : state->timeout_handler = tevent_add_timer(ev, req, tv,
398 : ipa_getkeytab_timeout, req);
399 0 : if(state->timeout_handler == NULL) {
400 0 : ret = ERR_IPA_GETKEYTAB_FAILED;
401 0 : goto done;
402 : }
403 :
404 : /* Now either wait for the timeout to fire or the child
405 : * to finish
406 : */
407 : } else { /* error */
408 0 : ret = errno;
409 0 : DEBUG(SSSDBG_CRIT_FAILURE,
410 : "fork failed [%d][%s].\n", ret, sss_strerror(ret));
411 0 : goto done;
412 : }
413 :
414 0 : ret = EOK;
415 : done:
416 0 : if (ret != EOK) {
417 0 : tevent_req_error(req, ret);
418 0 : tevent_req_post(req, ev);
419 : }
420 0 : return req;
421 : }
422 :
423 0 : static void ipa_getkeytab_exec(const char *ccache,
424 : const char *server,
425 : const char *principal,
426 : const char *keytab_path)
427 : {
428 : errno_t ret;
429 : int debug_fd;
430 0 : const char *gkt_env[2] = { NULL, NULL };
431 :
432 0 : if (debug_level >= SSSDBG_TRACE_LIBS) {
433 0 : debug_fd = get_fd_from_debug_file();
434 0 : ret = dup2(debug_fd, STDERR_FILENO);
435 0 : if (ret == -1) {
436 0 : ret = errno;
437 0 : DEBUG(SSSDBG_MINOR_FAILURE,
438 : "dup2 failed [%d][%s].\n", ret, sss_strerror(ret));
439 : /* stderr is not fatal */
440 : }
441 : }
442 :
443 0 : gkt_env[0] = talloc_asprintf(NULL, "KRB5CCNAME=%s", ccache);
444 0 : if (gkt_env[0] == NULL) {
445 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to format KRB5CCNAME\n");
446 0 : exit(1);
447 : }
448 :
449 : /* ipa-getkeytab cannot add keys to an empty file, let's unlink it and only
450 : * use the filename */
451 0 : ret = unlink(keytab_path);
452 0 : if (ret == -1) {
453 0 : ret = errno;
454 0 : DEBUG(SSSDBG_CRIT_FAILURE,
455 : "Failed to unlink the temporary ccname [%d][%s]\n",
456 : ret, sss_strerror(ret));
457 0 : exit(1);
458 : }
459 :
460 0 : errno = 0;
461 0 : ret = execle(IPA_GETKEYTAB_PATH, IPA_GETKEYTAB_PATH,
462 : "-r", "-s", server, "-p", principal, "-k", keytab_path, NULL,
463 : gkt_env);
464 :
465 0 : DEBUG(SSSDBG_CRIT_FAILURE,
466 : "execle returned %d, this shouldn't happen!\n", ret);
467 :
468 : /* The child should never end up here */
469 0 : ret = errno;
470 0 : DEBUG(SSSDBG_CRIT_FAILURE,
471 : "execle failed [%d][%s].\n", ret, sss_strerror(ret));
472 0 : exit(1);
473 : }
474 :
475 0 : static void ipa_getkeytab_done(int child_status,
476 : struct tevent_signal *sige,
477 : void *pvt)
478 : {
479 0 : struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
480 0 : struct ipa_getkeytab_state *state =
481 0 : tevent_req_data(req, struct ipa_getkeytab_state);
482 :
483 0 : state->child_status = child_status;
484 :
485 0 : if (WIFEXITED(child_status) && WEXITSTATUS(child_status) != 0) {
486 0 : DEBUG(SSSDBG_OP_FAILURE,
487 : "ipa-getkeytab failed with status [%d]\n", child_status);
488 0 : tevent_req_error(req, ERR_IPA_GETKEYTAB_FAILED);
489 0 : return;
490 : }
491 :
492 0 : if (WIFSIGNALED(child_status)) {
493 0 : DEBUG(SSSDBG_OP_FAILURE,
494 : "ipa-getkeytab was terminated by signal [%d]\n",
495 : WTERMSIG(child_status));
496 0 : tevent_req_error(req, ERR_IPA_GETKEYTAB_FAILED);
497 0 : return;
498 : }
499 :
500 0 : tevent_req_done(req);
501 : }
502 :
503 0 : static void ipa_getkeytab_timeout(struct tevent_context *ev,
504 : struct tevent_timer *te,
505 : struct timeval tv, void *pvt)
506 : {
507 0 : struct tevent_req *req =
508 : talloc_get_type(pvt, struct tevent_req);
509 0 : struct ipa_getkeytab_state *state =
510 0 : tevent_req_data(req, struct ipa_getkeytab_state);
511 :
512 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Timeout reached for retrieving keytab from IPA server\n");
513 0 : child_handler_destroy(state->child_ctx);
514 0 : state->child_ctx = NULL;
515 0 : state->child_status = ETIMEDOUT;
516 0 : tevent_req_error(req, ERR_IPA_GETKEYTAB_FAILED);
517 0 : }
518 :
519 0 : static errno_t ipa_getkeytab_recv(struct tevent_req *req, int *child_status)
520 : {
521 0 : struct ipa_getkeytab_state *state =
522 0 : tevent_req_data(req, struct ipa_getkeytab_state);
523 :
524 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
525 : "ipa-getkeytab status %d\n", state->child_status);
526 0 : if (child_status) {
527 0 : *child_status = state->child_status;
528 : }
529 :
530 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
531 :
532 0 : return EOK;
533 : }
534 :
535 0 : static errno_t ipa_check_keytab(const char *keytab,
536 : uid_t kt_owner_uid,
537 : gid_t kt_owner_gid)
538 : {
539 : errno_t ret;
540 :
541 0 : ret = check_file(keytab, getuid(), getgid(), S_IFREG|0600, 0, NULL, false);
542 0 : if (ret == ENOENT) {
543 0 : DEBUG(SSSDBG_TRACE_FUNC, "Keytab %s is not present\n", keytab);
544 0 : goto done;
545 0 : } else if (ret != EOK) {
546 0 : if (kt_owner_uid) {
547 0 : ret = check_file(keytab, kt_owner_uid, kt_owner_gid,
548 : S_IFREG|0600, 0, NULL, false);
549 : }
550 :
551 0 : if (ret != EOK) {
552 0 : if (ret != ENOENT) {
553 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to check for %s\n", keytab);
554 : } else {
555 0 : DEBUG(SSSDBG_TRACE_FUNC, "Keytab %s is not present\n", keytab);
556 : }
557 : }
558 0 : goto done;
559 : }
560 :
561 0 : DEBUG(SSSDBG_TRACE_ALL, "keytab %s already exists\n", keytab);
562 0 : ret = EOK;
563 : done:
564 0 : return ret;
565 : }
566 :
567 : struct ipa_server_trusted_dom_setup_state {
568 : struct tevent_context *ev;
569 : struct be_ctx *be_ctx;
570 : struct ipa_id_ctx *id_ctx;
571 : struct sss_domain_info *subdom;
572 :
573 : uint32_t direction;
574 : const char *forest;
575 : const char *keytab;
576 : char *new_keytab;
577 : const char *principal;
578 : const char *forest_realm;
579 : const char *ccache;
580 : };
581 :
582 : static errno_t ipa_server_trusted_dom_setup_1way(struct tevent_req *req);
583 : static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq);
584 :
585 : struct tevent_req *
586 0 : ipa_server_trusted_dom_setup_send(TALLOC_CTX *mem_ctx,
587 : struct tevent_context *ev,
588 : struct be_ctx *be_ctx,
589 : struct ipa_id_ctx *id_ctx,
590 : struct sss_domain_info *subdom)
591 : {
592 0 : struct tevent_req *req = NULL;
593 0 : struct ipa_server_trusted_dom_setup_state *state = NULL;
594 : errno_t ret;
595 :
596 0 : req = tevent_req_create(mem_ctx, &state,
597 : struct ipa_server_trusted_dom_setup_state);
598 0 : if (req == NULL) {
599 0 : return NULL;
600 : }
601 0 : state->ev = ev;
602 0 : state->be_ctx = be_ctx;
603 0 : state->id_ctx = id_ctx;
604 0 : state->subdom = subdom;
605 :
606 : /* Trusts are only established with forest roots */
607 0 : if (subdom->forest_root == NULL) {
608 0 : DEBUG(SSSDBG_OP_FAILURE,
609 : "Subdomain %s has no forest root?\n", subdom->name);
610 0 : ret = ERR_TRUST_FOREST_UNKNOWN;
611 0 : goto immediate;
612 : }
613 :
614 0 : state->direction = subdom->forest_root->trust_direction;
615 0 : state->forest = subdom->forest_root->forest;
616 0 : state->forest_realm = subdom->forest_root->realm;
617 0 : state->ccache = talloc_asprintf(state, "%s/ccache_%s",
618 0 : DB_PATH, subdom->parent->realm);
619 0 : if (state->ccache == NULL) {
620 0 : ret = ENOMEM;
621 0 : goto immediate;
622 : }
623 :
624 0 : DEBUG(SSSDBG_TRACE_LIBS,
625 : "Trust direction of subdom %s from forest %s is: %s\n",
626 : subdom->name, state->forest,
627 : ipa_trust_dir2str(state->direction));
628 :
629 0 : if (state->direction & LSA_TRUST_DIRECTION_OUTBOUND) {
630 : /* Use system keytab, nothing to do here */
631 0 : ret = EOK;
632 0 : goto immediate;
633 0 : } else if (state->direction & LSA_TRUST_DIRECTION_INBOUND) {
634 : /* Need special keytab */
635 0 : ret = ipa_server_trusted_dom_setup_1way(req);
636 0 : if (ret == EAGAIN) {
637 : /* In progress.. */
638 0 : return req;
639 0 : } else if (ret == EOK) {
640 : /* Keytab available, shortcut */
641 0 : ret = EOK;
642 0 : goto immediate;
643 : }
644 : } else {
645 : /* Even unset is an error at this point */
646 0 : DEBUG(SSSDBG_OP_FAILURE,
647 : "Subdomain %s has trust direction %d\n",
648 : subdom->name, subdom->trust_direction);
649 0 : ret = ERR_TRUST_NOT_SUPPORTED;
650 : }
651 :
652 : immediate:
653 0 : if (ret != EOK) {
654 0 : DEBUG(SSSDBG_OP_FAILURE,
655 : "Could not add trusted subdomain %s from forest %s\n",
656 : subdom->name, state->forest);
657 0 : tevent_req_error(req, ret);
658 : } else {
659 0 : tevent_req_done(req);
660 : }
661 0 : tevent_req_post(req, ev);
662 0 : return req;
663 : }
664 :
665 0 : static errno_t ipa_server_trusted_dom_setup_1way(struct tevent_req *req)
666 : {
667 : errno_t ret;
668 0 : struct tevent_req *subreq = NULL;
669 0 : struct ipa_server_trusted_dom_setup_state *state =
670 0 : tevent_req_data(req, struct ipa_server_trusted_dom_setup_state);
671 : const char *hostname;
672 :
673 0 : state->keytab = forest_keytab(state, state->forest);
674 0 : if (state->keytab == NULL) {
675 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set up ipa_get_keytab\n");
676 0 : return EIO;
677 : }
678 :
679 0 : state->new_keytab = talloc_asprintf(state, "%sXXXXXX", state->keytab);
680 0 : if (state->new_keytab == NULL) {
681 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set up ipa_get_keytab\n");
682 0 : return ENOMEM;
683 : }
684 :
685 0 : ret = sss_unique_filename(state, state->new_keytab);
686 0 : if (ret != EOK) {
687 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create temporary keytab name\n");
688 0 : return ret;
689 : }
690 :
691 0 : DEBUG(SSSDBG_TRACE_FUNC,
692 : "Will re-fetch keytab for %s\n", state->subdom->name);
693 :
694 0 : hostname = dp_opt_get_string(state->id_ctx->ipa_options->basic,
695 : IPA_HOSTNAME);
696 :
697 0 : state->principal = subdomain_trust_princ(state,
698 : state->forest_realm,
699 : state->subdom);
700 0 : if (state->principal == NULL) {
701 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set up ipa_get_keytab\n");
702 0 : return EIO;
703 : }
704 :
705 0 : subreq = ipa_getkeytab_send(state->be_ctx, state->be_ctx->ev,
706 : state->ccache,
707 : hostname,
708 : state->principal,
709 0 : state->new_keytab);
710 0 : if (subreq == NULL) {
711 0 : return ENOMEM;
712 : }
713 0 : tevent_req_set_callback(subreq, ipa_server_trust_1way_kt_done, req);
714 0 : return EAGAIN;
715 : }
716 :
717 0 : static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq)
718 : {
719 : errno_t ret;
720 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
721 : struct tevent_req);
722 0 : struct ipa_server_trusted_dom_setup_state *state =
723 0 : tevent_req_data(req, struct ipa_server_trusted_dom_setup_state);
724 :
725 0 : ret = ipa_getkeytab_recv(subreq, NULL);
726 0 : talloc_zfree(subreq);
727 0 : if (ret != EOK) {
728 : /* Do not fail here, but try to check and use the previous keytab,
729 : * if any */
730 0 : DEBUG(SSSDBG_MINOR_FAILURE, "ipa_getkeytab_recv failed: %d\n", ret);
731 : } else {
732 0 : DEBUG(SSSDBG_TRACE_FUNC,
733 : "Keytab successfully retrieved to %s\n", state->new_keytab);
734 : }
735 :
736 0 : ret = ipa_check_keytab(state->new_keytab,
737 0 : state->id_ctx->server_mode->kt_owner_uid,
738 0 : state->id_ctx->server_mode->kt_owner_gid);
739 0 : if (ret == EOK) {
740 0 : ret = rename(state->new_keytab, state->keytab);
741 0 : if (ret == -1) {
742 0 : ret = errno;
743 0 : DEBUG(SSSDBG_CRIT_FAILURE,
744 : "rename failed [%d][%s].\n", ret, strerror(ret));
745 0 : tevent_req_error(req, ret);
746 0 : return;
747 : }
748 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "Keytab renamed to %s\n", state->keytab);
749 0 : } else if (ret != EOK) {
750 0 : DEBUG(SSSDBG_MINOR_FAILURE,
751 : "Trying to recover and use the previous keytab, if available\n");
752 0 : ret = ipa_check_keytab(state->keytab,
753 0 : state->id_ctx->server_mode->kt_owner_uid,
754 0 : state->id_ctx->server_mode->kt_owner_gid);
755 0 : if (ret == EOK) {
756 0 : DEBUG(SSSDBG_TRACE_FUNC,
757 : "The previous keytab %s contains the expected principal\n",
758 : state->keytab);
759 : } else {
760 0 : DEBUG(SSSDBG_OP_FAILURE,
761 : "Cannot use the old keytab: %d\n", ret);
762 : /* Nothing we can do now */
763 0 : tevent_req_error(req, ret);
764 0 : return;
765 : }
766 : }
767 :
768 0 : DEBUG(SSSDBG_TRACE_FUNC,
769 : "Keytab %s contains the expected principals\n", state->new_keytab);
770 :
771 0 : DEBUG(SSSDBG_TRACE_FUNC,
772 : "Established trust context for %s\n", state->subdom->name);
773 0 : tevent_req_done(req);
774 : }
775 :
776 0 : errno_t ipa_server_trusted_dom_setup_recv(struct tevent_req *req)
777 : {
778 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
779 0 : return EOK;
780 : }
781 :
782 : struct ipa_server_create_trusts_state {
783 : struct tevent_context *ev;
784 : struct be_ctx *be_ctx;
785 : struct ipa_id_ctx *id_ctx;
786 : struct sss_domain_info *domiter;
787 : };
788 :
789 : static errno_t ipa_server_create_trusts_step(struct tevent_req *req);
790 : static errno_t ipa_server_create_trusts_ctx(struct tevent_req *req);
791 : static void ipa_server_create_trusts_done(struct tevent_req *subreq);
792 :
793 : struct tevent_req *
794 0 : ipa_server_create_trusts_send(TALLOC_CTX *mem_ctx,
795 : struct tevent_context *ev,
796 : struct be_ctx *be_ctx,
797 : struct ipa_id_ctx *id_ctx,
798 : struct sss_domain_info *parent)
799 : {
800 0 : struct tevent_req *req = NULL;
801 0 : struct ipa_server_create_trusts_state *state = NULL;
802 : errno_t ret;
803 :
804 0 : req = tevent_req_create(mem_ctx, &state,
805 : struct ipa_server_create_trusts_state);
806 0 : if (req == NULL) {
807 0 : return NULL;
808 : }
809 :
810 0 : state->ev = ev;
811 0 : state->be_ctx = be_ctx;
812 0 : state->id_ctx = id_ctx;
813 0 : state->domiter = parent;
814 :
815 0 : ret = ipa_server_create_trusts_step(req);
816 0 : if (ret != EAGAIN) {
817 0 : goto immediate;
818 : }
819 :
820 0 : return req;
821 :
822 : immediate:
823 0 : if (ret != EOK) {
824 0 : tevent_req_error(req, ret);
825 : } else {
826 0 : tevent_req_done(req);
827 : }
828 0 : tevent_req_post(req, ev);
829 0 : return req;
830 : }
831 :
832 0 : static errno_t ipa_server_create_trusts_step(struct tevent_req *req)
833 : {
834 0 : struct tevent_req *subreq = NULL;
835 : struct ipa_ad_server_ctx *trust_iter;
836 0 : struct ipa_server_create_trusts_state *state = NULL;
837 :
838 0 : state = tevent_req_data(req, struct ipa_server_create_trusts_state);
839 :
840 0 : for (state->domiter = get_next_domain(state->domiter, SSS_GND_DESCEND);
841 0 : state->domiter && IS_SUBDOMAIN(state->domiter);
842 0 : state->domiter = get_next_domain(state->domiter, 0)) {
843 :
844 : /* Check if we already have an ID context for this subdomain */
845 0 : DLIST_FOR_EACH(trust_iter, state->id_ctx->server_mode->trusts) {
846 0 : if (trust_iter->dom == state->domiter) {
847 0 : break;
848 : }
849 : }
850 :
851 : /* Newly detected trust */
852 0 : if (trust_iter == NULL) {
853 0 : subreq = ipa_server_trusted_dom_setup_send(state,
854 : state->ev,
855 : state->be_ctx,
856 : state->id_ctx,
857 : state->domiter);
858 0 : if (subreq == NULL) {
859 0 : return ENOMEM;
860 : }
861 0 : tevent_req_set_callback(subreq, ipa_server_create_trusts_done, req);
862 0 : return EAGAIN;
863 : }
864 : }
865 :
866 0 : return EOK;
867 : }
868 :
869 0 : static void ipa_server_create_trusts_done(struct tevent_req *subreq)
870 : {
871 : errno_t ret;
872 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
873 : struct tevent_req);
874 :
875 0 : ret = ipa_server_trusted_dom_setup_recv(subreq);
876 0 : talloc_zfree(subreq);
877 0 : if (ret != EOK) {
878 0 : tevent_req_error(req, ret);
879 0 : return;
880 : }
881 :
882 0 : ret = ipa_server_create_trusts_ctx(req);
883 0 : if (ret != EOK) {
884 0 : tevent_req_error(req, ret);
885 0 : return;
886 : }
887 :
888 0 : ret = ipa_server_create_trusts_step(req);
889 0 : if (ret == EOK) {
890 0 : tevent_req_done(req);
891 0 : return;
892 0 : } else if (ret != EAGAIN) {
893 0 : tevent_req_error(req, ret);
894 0 : return;
895 : }
896 :
897 : /* Will cycle back */
898 : }
899 :
900 0 : static errno_t ipa_server_create_trusts_ctx(struct tevent_req *req)
901 : {
902 : struct ipa_ad_server_ctx *trust_ctx;
903 : struct ad_id_ctx *ad_id_ctx;
904 : errno_t ret;
905 0 : struct ipa_server_create_trusts_state *state = NULL;
906 :
907 0 : state = tevent_req_data(req, struct ipa_server_create_trusts_state);
908 :
909 0 : ret = ipa_ad_ctx_new(state->be_ctx, state->id_ctx, state->domiter, &ad_id_ctx);
910 0 : if (ret != EOK) {
911 0 : DEBUG(SSSDBG_OP_FAILURE,
912 : "Cannot create ad_id_ctx for subdomain %s\n", state->domiter->name);
913 0 : return ret;
914 : }
915 :
916 0 : trust_ctx = talloc(state->id_ctx->server_mode, struct ipa_ad_server_ctx);
917 0 : if (trust_ctx == NULL) {
918 0 : return ENOMEM;
919 : }
920 0 : trust_ctx->dom = state->domiter;
921 0 : trust_ctx->ad_id_ctx = ad_id_ctx;
922 :
923 0 : DLIST_ADD(state->id_ctx->server_mode->trusts, trust_ctx);
924 0 : return EOK;
925 : }
926 :
927 0 : errno_t ipa_server_create_trusts_recv(struct tevent_req *req)
928 : {
929 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
930 0 : return EOK;
931 : }
932 :
933 0 : void ipa_ad_subdom_remove(struct be_ctx *be_ctx,
934 : struct ipa_id_ctx *id_ctx,
935 : struct sss_domain_info *subdom)
936 : {
937 : struct ipa_ad_server_ctx *iter;
938 : struct sdap_domain *sdom;
939 :
940 0 : if (dp_opt_get_bool(id_ctx->ipa_options->basic,
941 0 : IPA_SERVER_MODE) == false) {
942 0 : return;
943 : }
944 :
945 0 : DLIST_FOR_EACH(iter, id_ctx->server_mode->trusts) {
946 0 : if (iter->dom == subdom) break;
947 : }
948 :
949 0 : if (iter == NULL) {
950 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No IPA-AD context for subdomain %s\n",
951 : subdom->name);
952 0 : return;
953 : }
954 :
955 0 : sdom = sdap_domain_get(iter->ad_id_ctx->sdap_id_ctx->opts, subdom);
956 0 : if (sdom == NULL) return;
957 0 : be_ptask_destroy(&sdom->enum_task);
958 0 : be_ptask_destroy(&sdom->cleanup_task);
959 :
960 0 : sdap_domain_remove(iter->ad_id_ctx->sdap_id_ctx->opts, subdom);
961 0 : DLIST_REMOVE(id_ctx->server_mode->trusts, iter);
962 :
963 : /* terminate all requests for this subdomain so we can free it */
964 0 : dp_terminate_domain_requests(be_ctx->provider, subdom->name);
965 0 : talloc_zfree(sdom);
966 : }
967 :
968 : struct ipa_ad_subdom_reinit_state {
969 : struct tevent_context *ev;
970 : struct be_ctx *be_ctx;
971 : struct ipa_id_ctx *id_ctx;
972 : struct sss_domain_info *parent;
973 : };
974 :
975 0 : static void create_trusts_at_startup_done(struct tevent_req *req)
976 : {
977 : errno_t ret;
978 :
979 0 : ret = ipa_server_create_trusts_recv(req);
980 0 : talloc_free(req);
981 0 : if (ret != EOK) {
982 0 : DEBUG(SSSDBG_MINOR_FAILURE,
983 : "ipa_server_create_trusts_send request failed [%d]: %s\n",
984 : ret, sss_strerror(ret));
985 : }
986 0 : }
987 :
988 0 : static void create_trusts_at_startup(struct tevent_context *ev,
989 : struct tevent_immediate *imm,
990 : void *pvt)
991 : {
992 : struct tevent_req *req;
993 : struct ipa_ad_subdom_reinit_state *state;
994 :
995 0 : state = talloc_get_type(pvt, struct ipa_ad_subdom_reinit_state);
996 :
997 0 : req = ipa_server_create_trusts_send(state, state->ev, state->be_ctx,
998 : state->id_ctx, state->parent);
999 0 : if (req == NULL) {
1000 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_server_create_trusts_send failed.\n");
1001 0 : talloc_free(state);
1002 0 : return;
1003 : }
1004 :
1005 0 : tevent_req_set_callback(req, create_trusts_at_startup_done, state);
1006 0 : return;
1007 : }
1008 :
1009 0 : static errno_t ipa_ad_subdom_reinit(TALLOC_CTX *mem_ctx,
1010 : struct tevent_context *ev,
1011 : struct be_ctx *be_ctx,
1012 : struct ipa_id_ctx *id_ctx,
1013 : struct sss_domain_info *parent)
1014 : {
1015 : struct tevent_immediate *imm;
1016 : struct ipa_ad_subdom_reinit_state *state;
1017 :
1018 0 : state = talloc(mem_ctx, struct ipa_ad_subdom_reinit_state);
1019 0 : if (state == NULL) {
1020 0 : return ENOMEM;
1021 : }
1022 0 : state->ev = ev;
1023 0 : state->be_ctx = be_ctx;
1024 0 : state->id_ctx = id_ctx;
1025 0 : state->parent = parent;
1026 :
1027 0 : if (dp_opt_get_bool(id_ctx->ipa_options->basic,
1028 0 : IPA_SERVER_MODE) == false) {
1029 0 : return EOK;
1030 : }
1031 :
1032 0 : imm = tevent_create_immediate(mem_ctx);
1033 0 : if (imm == NULL) {
1034 0 : DEBUG(SSSDBG_OP_FAILURE, "tevent_create_immediate failed.\n");
1035 0 : talloc_free(state);
1036 0 : return ENOMEM;
1037 : }
1038 :
1039 0 : tevent_schedule_immediate(imm, ev, create_trusts_at_startup, state);
1040 0 : return EOK;
1041 : }
1042 :
1043 0 : int ipa_ad_subdom_init(struct be_ctx *be_ctx,
1044 : struct ipa_id_ctx *id_ctx)
1045 : {
1046 : char *realm;
1047 : char *hostname;
1048 : errno_t ret;
1049 :
1050 0 : if (dp_opt_get_bool(id_ctx->ipa_options->basic,
1051 0 : IPA_SERVER_MODE) == false) {
1052 0 : return EOK;
1053 : }
1054 :
1055 : /* The IPA code relies on the default FQDN format to unparse user
1056 : * names. Warn loudly if the full_name_format was customized on the
1057 : * IPA server
1058 : */
1059 0 : if ((strcmp(be_ctx->domain->names->fq_fmt,
1060 : CONFDB_DEFAULT_FULL_NAME_FORMAT) != 0)
1061 0 : && (strcmp(be_ctx->domain->names->fq_fmt,
1062 : CONFDB_DEFAULT_FULL_NAME_FORMAT_INTERNAL) != 0)) {
1063 0 : DEBUG(SSSDBG_FATAL_FAILURE, "%s is set to a non-default value [%s] " \
1064 : "lookups of subdomain users will likely fail!\n",
1065 : CONFDB_FULL_NAME_FORMAT, be_ctx->domain->names->fq_fmt);
1066 0 : sss_log(SSS_LOG_ERR, "%s is set to a non-default value [%s] " \
1067 : "lookups of subdomain users will likely fail!\n",
1068 0 : CONFDB_FULL_NAME_FORMAT, be_ctx->domain->names->fq_fmt);
1069 : /* Attempt to continue */
1070 : }
1071 :
1072 0 : realm = dp_opt_get_string(id_ctx->ipa_options->basic, IPA_KRB5_REALM);
1073 0 : if (realm == NULL) {
1074 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm for IPA?\n");
1075 0 : return EINVAL;
1076 : }
1077 :
1078 0 : hostname = dp_opt_get_string(id_ctx->ipa_options->basic, IPA_HOSTNAME);
1079 0 : if (hostname == NULL) {
1080 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No host name for IPA?\n");
1081 0 : return EINVAL;
1082 : }
1083 :
1084 0 : id_ctx->server_mode = talloc_zero(id_ctx, struct ipa_server_mode_ctx);
1085 0 : if (id_ctx->server_mode == NULL) {
1086 0 : return ENOMEM;
1087 : }
1088 0 : id_ctx->server_mode->realm = realm;
1089 0 : id_ctx->server_mode->hostname = hostname;
1090 0 : id_ctx->server_mode->trusts = NULL;
1091 0 : id_ctx->server_mode->ext_groups = NULL;
1092 0 : id_ctx->server_mode->kt_owner_uid = 0;
1093 0 : id_ctx->server_mode->kt_owner_gid = 0;
1094 :
1095 0 : if (getuid() == 0) {
1096 : /* We need to handle keytabs created by IPA oddjob script gracefully
1097 : * even if we're running as root and IPA creates them as the SSSD user
1098 : */
1099 0 : ret = sss_user_by_name_or_uid(SSSD_USER,
1100 0 : &id_ctx->server_mode->kt_owner_uid,
1101 0 : &id_ctx->server_mode->kt_owner_gid);
1102 0 : if (ret != EOK) {
1103 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Failed to get ID of %s\n", SSSD_USER);
1104 : }
1105 : }
1106 :
1107 0 : ret = ipa_ad_subdom_reinit(be_ctx, be_ctx->ev,
1108 : be_ctx, id_ctx, be_ctx->domain);
1109 0 : if (ret != EOK) {
1110 0 : DEBUG(SSSDBG_OP_FAILURE, "ipa_ad_subdom_refresh failed.\n");
1111 0 : return ret;
1112 : }
1113 :
1114 0 : return EOK;
1115 : }
|