Line data Source code
1 : /*
2 : SSSD
3 :
4 : LDAP Provider Initialization functions
5 :
6 : Authors:
7 : Simo Sorce <ssorce@redhat.com>
8 :
9 : Copyright (C) 2009 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 "util/child_common.h"
26 : #include "providers/ldap/ldap_common.h"
27 : #include "providers/ldap/sdap_async_private.h"
28 : #include "providers/ldap/sdap_access.h"
29 : #include "providers/ldap/sdap_sudo.h"
30 : #include "providers/ldap/sdap_autofs.h"
31 : #include "providers/ldap/sdap_idmap.h"
32 : #include "providers/fail_over_srv.h"
33 : #include "providers/dp_refresh.h"
34 :
35 : static void sdap_shutdown(struct be_req *req);
36 :
37 : /* Id Handler */
38 : struct bet_ops sdap_id_ops = {
39 : .handler = sdap_account_info_handler,
40 : .finalize = sdap_shutdown,
41 : .check_online = sdap_check_online
42 : };
43 :
44 : /* Auth Handler */
45 : struct bet_ops sdap_auth_ops = {
46 : .handler = sdap_pam_auth_handler,
47 : .finalize = sdap_shutdown
48 : };
49 :
50 : /* Chpass Handler */
51 : struct bet_ops sdap_chpass_ops = {
52 : .handler = sdap_pam_chpass_handler,
53 : .finalize = sdap_shutdown
54 : };
55 :
56 : /* Access Handler */
57 : struct bet_ops sdap_access_ops = {
58 : .handler = sdap_pam_access_handler,
59 : .finalize = sdap_shutdown
60 : };
61 :
62 : /* Please use this only for short lists */
63 0 : errno_t check_order_list_for_duplicates(char **list,
64 : bool case_sensitive)
65 : {
66 : size_t c;
67 : size_t d;
68 : int cmp;
69 :
70 0 : for (c = 0; list[c] != NULL; c++) {
71 0 : for (d = c + 1; list[d] != NULL; d++) {
72 0 : if (case_sensitive) {
73 0 : cmp = strcmp(list[c], list[d]);
74 : } else {
75 0 : cmp = strcasecmp(list[c], list[d]);
76 : }
77 0 : if (cmp == 0) {
78 0 : DEBUG(SSSDBG_CRIT_FAILURE,
79 : "Duplicate string [%s] found.\n", list[c]);
80 0 : return EINVAL;
81 : }
82 : }
83 : }
84 :
85 0 : return EOK;
86 : }
87 :
88 0 : static int ldap_id_init_internal(struct be_ctx *bectx,
89 : struct bet_ops **ops,
90 : void **pvt_data)
91 : {
92 0 : struct sdap_id_ctx *ctx = NULL;
93 : const char *urls;
94 : const char *backup_urls;
95 : const char *dns_service_name;
96 : const char *sasl_mech;
97 : struct sdap_service *sdap_service;
98 0 : struct sdap_options *opts = NULL;
99 : int ret;
100 :
101 : /* If we're already set up, just return that */
102 0 : if(bectx->bet_info[BET_ID].mod_name &&
103 0 : strcmp("ldap", bectx->bet_info[BET_ID].mod_name) == 0) {
104 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
105 : "Re-using sdap_id_ctx for this provider\n");
106 0 : *ops = bectx->bet_info[BET_ID].bet_ops;
107 0 : *pvt_data = bectx->bet_info[BET_ID].pvt_bet_data;
108 0 : return EOK;
109 : }
110 :
111 0 : ret = ldap_get_options(bectx, bectx->domain, bectx->cdb,
112 : bectx->conf_path, &opts);
113 0 : if (ret != EOK) {
114 0 : goto done;
115 : }
116 :
117 0 : dns_service_name = dp_opt_get_string(opts->basic,
118 : SDAP_DNS_SERVICE_NAME);
119 0 : DEBUG(SSSDBG_CONF_SETTINGS,
120 : "Service name for discovery set to %s\n", dns_service_name);
121 :
122 0 : urls = dp_opt_get_string(opts->basic, SDAP_URI);
123 0 : backup_urls = dp_opt_get_string(opts->basic, SDAP_BACKUP_URI);
124 :
125 0 : ret = sdap_service_init(bectx, bectx, "LDAP",
126 : dns_service_name, urls, backup_urls,
127 : &sdap_service);
128 0 : if (ret != EOK) {
129 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to initialize failover service!\n");
130 0 : goto done;
131 : }
132 :
133 0 : ctx = sdap_id_ctx_new(bectx, bectx, sdap_service);
134 0 : if (!ctx) {
135 0 : ret = ENOMEM;
136 0 : goto done;
137 : }
138 0 : ctx->opts = talloc_steal(ctx, opts);
139 :
140 0 : sasl_mech = dp_opt_get_string(ctx->opts->basic, SDAP_SASL_MECH);
141 0 : if (sasl_mech && strcasecmp(sasl_mech, "GSSAPI") == 0) {
142 0 : if (dp_opt_get_bool(ctx->opts->basic, SDAP_KRB5_KINIT)) {
143 0 : ret = sdap_gssapi_init(ctx, ctx->opts->basic,
144 0 : ctx->be, ctx->conn->service,
145 : &ctx->krb5_service);
146 0 : if (ret != EOK) {
147 0 : DEBUG(SSSDBG_CRIT_FAILURE,
148 : "sdap_gssapi_init failed [%d][%s].\n",
149 : ret, strerror(ret));
150 0 : goto done;
151 : }
152 : }
153 : }
154 :
155 0 : ret = setup_tls_config(ctx->opts->basic);
156 0 : if (ret != EOK) {
157 0 : DEBUG(SSSDBG_CRIT_FAILURE, "setup_tls_config failed [%d][%s].\n",
158 : ret, strerror(ret));
159 0 : goto done;
160 : }
161 :
162 : /* Set up the ID mapping object */
163 0 : ret = sdap_idmap_init(ctx, ctx, &ctx->opts->idmap_ctx);
164 0 : if (ret != EOK) goto done;
165 :
166 0 : ret = sdap_setup_child();
167 0 : if (ret != EOK) {
168 0 : DEBUG(SSSDBG_CRIT_FAILURE, "setup_child failed [%d][%s].\n",
169 : ret, strerror(ret));
170 0 : goto done;
171 : }
172 :
173 : /* setup SRV lookup plugin */
174 0 : ret = be_fo_set_dns_srv_lookup_plugin(bectx, NULL);
175 0 : if (ret != EOK) {
176 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set SRV lookup plugin "
177 : "[%d]: %s\n", ret, strerror(ret));
178 0 : goto done;
179 : }
180 :
181 : /* setup periodical refresh of expired records */
182 0 : ret = sdap_refresh_init(bectx->refresh_ctx, ctx);
183 0 : if (ret != EOK && ret != EEXIST) {
184 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Periodical refresh "
185 : "will not work [%d]: %s\n", ret, strerror(ret));
186 : }
187 :
188 0 : *ops = &sdap_id_ops;
189 0 : *pvt_data = ctx;
190 0 : ret = EOK;
191 :
192 : done:
193 0 : if (ret != EOK) {
194 0 : talloc_free(opts);
195 0 : talloc_free(ctx);
196 : }
197 0 : return ret;
198 : }
199 :
200 0 : int sssm_ldap_id_init(struct be_ctx *bectx,
201 : struct bet_ops **ops,
202 : void **pvt_data)
203 : {
204 : int ret;
205 0 : struct sdap_id_ctx *ctx = NULL;
206 :
207 0 : ret = ldap_id_init_internal(bectx, ops, (void **) &ctx);
208 0 : if (ret != EOK) {
209 0 : DEBUG(SSSDBG_MINOR_FAILURE,
210 : "ldap_id_init_internal failed [%d][%s].\n",
211 : ret, strerror(ret));
212 0 : goto done;
213 : }
214 :
215 0 : ret = ldap_id_setup_tasks(ctx);
216 0 : if (ret != EOK) {
217 0 : DEBUG(SSSDBG_MINOR_FAILURE,
218 : "sdap_id_setup_tasks failed [%d][%s].\n",
219 : ret, strerror(ret));
220 0 : goto done;
221 : }
222 :
223 0 : *pvt_data = ctx;
224 0 : ret = EOK;
225 :
226 : done:
227 0 : if (ret != EOK) {
228 0 : talloc_free(ctx);
229 : }
230 0 : return ret;
231 : }
232 :
233 0 : int sssm_ldap_auth_init(struct be_ctx *bectx,
234 : struct bet_ops **ops,
235 : void **pvt_data)
236 : {
237 : void *data;
238 : struct sdap_id_ctx *id_ctx;
239 : struct sdap_auth_ctx *ctx;
240 : int ret;
241 :
242 0 : ret = ldap_id_init_internal(bectx, ops, &data);
243 0 : if (ret == EOK) {
244 0 : id_ctx = talloc_get_type(data, struct sdap_id_ctx);
245 :
246 0 : ctx = talloc(bectx, struct sdap_auth_ctx);
247 0 : if (!ctx) return ENOMEM;
248 :
249 0 : ctx->be = bectx;
250 0 : ctx->opts = id_ctx->opts;
251 0 : ctx->service = id_ctx->conn->service;
252 0 : ctx->chpass_service = NULL;
253 :
254 0 : *ops = &sdap_auth_ops;
255 0 : *pvt_data = ctx;
256 : }
257 :
258 0 : return ret;
259 : }
260 :
261 0 : int sssm_ldap_chpass_init(struct be_ctx *bectx,
262 : struct bet_ops **ops,
263 : void **pvt_data)
264 : {
265 : int ret;
266 : void *data;
267 0 : struct sdap_auth_ctx *ctx = NULL;
268 : const char *urls;
269 : const char *backup_urls;
270 : const char *dns_service_name;
271 :
272 0 : ret = sssm_ldap_auth_init(bectx, ops, &data);
273 0 : if (ret != EOK) {
274 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sssm_ldap_auth_init failed.\n");
275 0 : goto done;
276 : }
277 :
278 0 : ctx = talloc_get_type(data, struct sdap_auth_ctx);
279 :
280 0 : dns_service_name = dp_opt_get_string(ctx->opts->basic,
281 : SDAP_CHPASS_DNS_SERVICE_NAME);
282 0 : if (dns_service_name) {
283 0 : DEBUG(SSSDBG_TRACE_LIBS,
284 : "Service name for chpass discovery set to %s\n",
285 : dns_service_name);
286 : }
287 :
288 0 : urls = dp_opt_get_string(ctx->opts->basic, SDAP_CHPASS_URI);
289 0 : backup_urls = dp_opt_get_string(ctx->opts->basic, SDAP_CHPASS_BACKUP_URI);
290 0 : if (!urls && !backup_urls && !dns_service_name) {
291 0 : DEBUG(SSSDBG_TRACE_ALL,
292 : "ldap_chpass_uri and ldap_chpass_dns_service_name not set, "
293 : "using ldap_uri.\n");
294 0 : ctx->chpass_service = NULL;
295 : } else {
296 0 : ret = sdap_service_init(ctx, ctx->be, "LDAP_CHPASS", dns_service_name,
297 : urls, backup_urls, &ctx->chpass_service);
298 0 : if (ret != EOK) {
299 0 : DEBUG(SSSDBG_CRIT_FAILURE,
300 : "Failed to initialize failover service!\n");
301 0 : goto done;
302 : }
303 : }
304 :
305 :
306 0 : *ops = &sdap_chpass_ops;
307 0 : *pvt_data = ctx;
308 0 : ret = EOK;
309 :
310 : done:
311 0 : if (ret != EOK) {
312 0 : talloc_free(ctx);
313 : }
314 0 : return ret;
315 : }
316 :
317 0 : int sssm_ldap_access_init(struct be_ctx *bectx,
318 : struct bet_ops **ops,
319 : void **pvt_data)
320 : {
321 : int ret;
322 : struct sdap_access_ctx *access_ctx;
323 : const char *filter;
324 : const char *order;
325 : char **order_list;
326 : int order_list_len;
327 : size_t c;
328 : const char *dummy;
329 :
330 0 : access_ctx = talloc_zero(bectx, struct sdap_access_ctx);
331 0 : if(access_ctx == NULL) {
332 0 : ret = ENOMEM;
333 0 : goto done;
334 : }
335 :
336 0 : ret = ldap_id_init_internal(bectx, ops, (void **)&access_ctx->id_ctx);
337 0 : if (ret != EOK) {
338 0 : DEBUG(SSSDBG_CRIT_FAILURE, "ldap_id_init_internal failed.\n");
339 0 : goto done;
340 : }
341 :
342 0 : order = dp_opt_get_cstring(access_ctx->id_ctx->opts->basic,
343 : SDAP_ACCESS_ORDER);
344 0 : if (order == NULL) {
345 0 : DEBUG(SSSDBG_CRIT_FAILURE,
346 : "ldap_access_order not given, using 'filter'.\n");
347 0 : order = "filter";
348 : }
349 :
350 0 : ret = split_on_separator(access_ctx, order, ',', true, true,
351 : &order_list, &order_list_len);
352 0 : if (ret != EOK) {
353 0 : DEBUG(SSSDBG_CRIT_FAILURE, "split_on_separator failed.\n");
354 0 : goto done;
355 : }
356 :
357 0 : ret = check_order_list_for_duplicates(order_list, false);
358 0 : if (ret != EOK) {
359 0 : DEBUG(SSSDBG_CRIT_FAILURE, "check_order_list_for_duplicates failed.\n");
360 0 : goto done;
361 : }
362 :
363 0 : if (order_list_len > LDAP_ACCESS_LAST) {
364 0 : DEBUG(SSSDBG_CRIT_FAILURE,
365 : "Currently only [%d] different access rules are supported.\n",
366 : LDAP_ACCESS_LAST);
367 0 : ret = EINVAL;
368 0 : goto done;
369 : }
370 :
371 0 : for (c = 0; order_list[c] != NULL; c++) {
372 0 : if (strcasecmp(order_list[c], LDAP_ACCESS_FILTER_NAME) == 0) {
373 0 : access_ctx->access_rule[c] = LDAP_ACCESS_FILTER;
374 :
375 0 : filter = dp_opt_get_cstring(access_ctx->id_ctx->opts->basic,
376 : SDAP_ACCESS_FILTER);
377 0 : if (filter == NULL) {
378 : /* It's okay if this is NULL. In that case we will simply act
379 : * like the 'deny' provider.
380 : */
381 0 : DEBUG(SSSDBG_FATAL_FAILURE,
382 : "Warning: LDAP access rule 'filter' is set, "
383 : "but no ldap_access_filter configured. "
384 : "All domain users will be denied access.\n");
385 : } else {
386 0 : access_ctx->filter = sdap_get_access_filter(access_ctx,
387 : filter);
388 0 : if (access_ctx->filter == NULL) {
389 0 : ret = ENOMEM;
390 0 : goto done;
391 : }
392 : }
393 0 : } else if (strcasecmp(order_list[c], LDAP_ACCESS_EXPIRE_NAME) == 0) {
394 0 : access_ctx->access_rule[c] = LDAP_ACCESS_EXPIRE;
395 :
396 0 : dummy = dp_opt_get_cstring(access_ctx->id_ctx->opts->basic,
397 : SDAP_ACCOUNT_EXPIRE_POLICY);
398 0 : if (dummy == NULL) {
399 0 : DEBUG(SSSDBG_FATAL_FAILURE,
400 : "Warning: LDAP access rule 'expire' is set, "
401 : "but no ldap_account_expire_policy configured. "
402 : "All domain users will be denied access.\n");
403 : } else {
404 0 : if (strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_SHADOW) != 0 &&
405 0 : strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_AD) != 0 &&
406 0 : strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_NDS) != 0 &&
407 0 : strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_RHDS) != 0 &&
408 0 : strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_IPA) != 0 &&
409 0 : strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_389DS) != 0) {
410 0 : DEBUG(SSSDBG_CRIT_FAILURE,
411 : "Unsupported LDAP account expire policy [%s].\n",
412 : dummy);
413 0 : ret = EINVAL;
414 0 : goto done;
415 : }
416 : }
417 0 : } else if (strcasecmp(order_list[c], LDAP_ACCESS_SERVICE_NAME) == 0) {
418 0 : access_ctx->access_rule[c] = LDAP_ACCESS_SERVICE;
419 0 : } else if (strcasecmp(order_list[c], LDAP_ACCESS_HOST_NAME) == 0) {
420 0 : access_ctx->access_rule[c] = LDAP_ACCESS_HOST;
421 0 : } else if (strcasecmp(order_list[c], LDAP_ACCESS_LOCK_NAME) == 0) {
422 0 : access_ctx->access_rule[c] = LDAP_ACCESS_LOCKOUT;
423 0 : } else if (strcasecmp(order_list[c],
424 : LDAP_ACCESS_EXPIRE_POLICY_REJECT_NAME) == 0) {
425 0 : access_ctx->access_rule[c] = LDAP_ACCESS_EXPIRE_POLICY_REJECT;
426 0 : } else if (strcasecmp(order_list[c],
427 : LDAP_ACCESS_EXPIRE_POLICY_WARN_NAME) == 0) {
428 0 : access_ctx->access_rule[c] = LDAP_ACCESS_EXPIRE_POLICY_WARN;
429 0 : } else if (strcasecmp(order_list[c],
430 : LDAP_ACCESS_EXPIRE_POLICY_RENEW_NAME) == 0) {
431 0 : access_ctx->access_rule[c] = LDAP_ACCESS_EXPIRE_POLICY_RENEW;
432 0 : } else if (strcasecmp(order_list[c], LDAP_ACCESS_PPOLICY_NAME) == 0) {
433 0 : access_ctx->access_rule[c] = LDAP_ACCESS_PPOLICY;
434 : } else {
435 0 : DEBUG(SSSDBG_CRIT_FAILURE,
436 : "Unexpected access rule name [%s].\n", order_list[c]);
437 0 : ret = EINVAL;
438 0 : goto done;
439 : }
440 : }
441 0 : access_ctx->access_rule[c] = LDAP_ACCESS_EMPTY;
442 0 : if (c == 0) {
443 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Warning: access_provider=ldap set, "
444 : "but ldap_access_order is empty. "
445 : "All domain users will be denied access.\n");
446 : }
447 :
448 0 : *ops = &sdap_access_ops;
449 0 : *pvt_data = access_ctx;
450 :
451 0 : ret = EOK;
452 :
453 : done:
454 0 : if (ret != EOK) {
455 0 : talloc_free(access_ctx);
456 : }
457 0 : return ret;
458 : }
459 :
460 0 : int sssm_ldap_sudo_init(struct be_ctx *be_ctx,
461 : struct bet_ops **ops,
462 : void **pvt_data)
463 : {
464 : #ifdef BUILD_SUDO
465 : struct sdap_id_ctx *id_ctx;
466 : void *data;
467 : int ret;
468 :
469 0 : ret = ldap_id_init_internal(be_ctx, ops, &data);
470 0 : if (ret != EOK) {
471 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot init LDAP ID provider [%d]: %s\n",
472 : ret, strerror(ret));
473 0 : return ret;
474 : }
475 :
476 0 : id_ctx = talloc_get_type(data, struct sdap_id_ctx);
477 0 : if (!id_ctx) {
478 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No ID provider?\n");
479 0 : return EIO;
480 : }
481 :
482 0 : return sdap_sudo_init(be_ctx, id_ctx, ops, pvt_data);
483 : #else
484 : DEBUG(SSSDBG_MINOR_FAILURE, "Sudo init handler called but SSSD is "
485 : "built without sudo support, ignoring\n");
486 : return EOK;
487 : #endif
488 : }
489 :
490 0 : int sssm_ldap_autofs_init(struct be_ctx *be_ctx,
491 : struct bet_ops **ops,
492 : void **pvt_data)
493 : {
494 : #ifdef BUILD_AUTOFS
495 : struct sdap_id_ctx *id_ctx;
496 : void *data;
497 : int ret;
498 :
499 0 : ret = ldap_id_init_internal(be_ctx, ops, &data);
500 0 : if (ret != EOK) {
501 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Cannot init LDAP ID provider [%d]: %s\n",
502 : ret, strerror(ret));
503 0 : return ret;
504 : }
505 :
506 0 : id_ctx = talloc_get_type(data, struct sdap_id_ctx);
507 0 : if (!id_ctx) {
508 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No ID provider?\n");
509 0 : return EIO;
510 : }
511 :
512 0 : return sdap_autofs_init(be_ctx, id_ctx, ops, pvt_data);
513 : #else
514 : DEBUG(SSSDBG_MINOR_FAILURE, "Autofs init handler called but SSSD is "
515 : "built without autofs support, ignoring\n");
516 : return EOK;
517 : #endif
518 : }
519 :
520 0 : static void sdap_shutdown(struct be_req *req)
521 : {
522 : /* TODO: Clean up any internal data */
523 0 : sdap_handler_done(req, DP_ERR_OK, EOK, NULL);
524 0 : }
525 :
|