Line data Source code
1 : /*
2 : SSSD
3 :
4 : LDAP Provider Common Functions
5 :
6 : Authors:
7 : Simo Sorce <ssorce@redhat.com>
8 :
9 : Copyright (C) 2008-2010 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/ldap_common.h"
26 : #include "providers/fail_over.h"
27 : #include "providers/ldap/sdap_async_private.h"
28 : #include "providers/krb5/krb5_common.h"
29 : #include "db/sysdb_sudo.h"
30 : #include "db/sysdb_services.h"
31 : #include "db/sysdb_autofs.h"
32 :
33 : #include "util/sss_krb5.h"
34 : #include "util/crypto/sss_crypto.h"
35 :
36 : #include "providers/ldap/sdap_idmap.h"
37 :
38 : /* a fd the child process would log into */
39 : int ldap_child_debug_fd = -1;
40 :
41 0 : int ldap_id_setup_tasks(struct sdap_id_ctx *ctx)
42 : {
43 0 : return sdap_id_setup_tasks(ctx->be, ctx, ctx->opts->sdom,
44 : ldap_enumeration_send,
45 : ldap_enumeration_recv,
46 : ctx);
47 : }
48 :
49 0 : int sdap_id_setup_tasks(struct be_ctx *be_ctx,
50 : struct sdap_id_ctx *ctx,
51 : struct sdap_domain *sdom,
52 : be_ptask_send_t send_fn,
53 : be_ptask_recv_t recv_fn,
54 : void *pvt)
55 : {
56 : int ret;
57 :
58 : /* set up enumeration task */
59 0 : if (sdom->dom->enumerate) {
60 0 : DEBUG(SSSDBG_TRACE_FUNC, "Setting up enumeration for %s\n",
61 : sdom->dom->name);
62 0 : ret = ldap_setup_enumeration(be_ctx, ctx->opts, sdom,
63 : send_fn, recv_fn, pvt);
64 : } else {
65 : /* the enumeration task, runs the cleanup process by itself,
66 : * but if enumeration is not running we need to schedule it */
67 0 : DEBUG(SSSDBG_TRACE_FUNC, "Setting up cleanup task for %s\n",
68 : sdom->dom->name);
69 0 : ret = ldap_setup_cleanup(ctx, sdom);
70 : }
71 :
72 0 : return ret;
73 : }
74 :
75 0 : static void sdap_uri_callback(void *private_data, struct fo_server *server)
76 : {
77 0 : TALLOC_CTX *tmp_ctx = NULL;
78 : struct sdap_service *service;
79 : struct resolv_hostent *srvaddr;
80 : struct sockaddr_storage *sockaddr;
81 : const char *tmp;
82 : const char *srv_name;
83 : char *new_uri;
84 :
85 0 : tmp_ctx = talloc_new(NULL);
86 0 : if (tmp_ctx == NULL) {
87 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed\n");
88 0 : return;
89 : }
90 :
91 0 : service = talloc_get_type(private_data, struct sdap_service);
92 0 : if (!service) {
93 0 : talloc_free(tmp_ctx);
94 0 : return;
95 : }
96 :
97 0 : tmp = (const char *)fo_get_server_user_data(server);
98 :
99 0 : srvaddr = fo_get_server_hostent(server);
100 0 : if (!srvaddr) {
101 0 : DEBUG(SSSDBG_CRIT_FAILURE,
102 : "FATAL: No hostent available for server (%s)\n",
103 : fo_get_server_str_name(server));
104 0 : talloc_free(tmp_ctx);
105 0 : return;
106 : }
107 :
108 0 : sockaddr = resolv_get_sockaddr_address(tmp_ctx, srvaddr,
109 : fo_get_server_port(server));
110 0 : if (sockaddr == NULL) {
111 0 : DEBUG(SSSDBG_CRIT_FAILURE, "resolv_get_sockaddr_address failed.\n");
112 0 : talloc_free(tmp_ctx);
113 0 : return;
114 : }
115 :
116 0 : if (fo_is_srv_lookup(server)) {
117 0 : if (!tmp) {
118 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unknown service, using ldap\n");
119 0 : tmp = SSS_LDAP_SRV_NAME;
120 : }
121 :
122 0 : srv_name = fo_get_server_name(server);
123 0 : if (srv_name == NULL) {
124 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not get server host name\n");
125 0 : talloc_free(tmp_ctx);
126 0 : return;
127 : }
128 :
129 0 : new_uri = talloc_asprintf(service, "%s://%s:%d",
130 : tmp, srv_name,
131 : fo_get_server_port(server));
132 : } else {
133 0 : new_uri = talloc_strdup(service, tmp);
134 : }
135 :
136 0 : if (!new_uri) {
137 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to copy URI ...\n");
138 0 : talloc_free(tmp_ctx);
139 0 : return;
140 : }
141 :
142 0 : DEBUG(SSSDBG_TRACE_FUNC, "Constructed uri '%s'\n", new_uri);
143 :
144 : /* free old one and replace with new one */
145 0 : talloc_zfree(service->uri);
146 0 : service->uri = new_uri;
147 0 : talloc_zfree(service->sockaddr);
148 0 : service->sockaddr = talloc_steal(service, sockaddr);
149 0 : talloc_free(tmp_ctx);
150 : }
151 :
152 0 : static void sdap_finalize(struct tevent_context *ev,
153 : struct tevent_signal *se,
154 : int signum,
155 : int count,
156 : void *siginfo,
157 : void *private_data)
158 : {
159 0 : char *realm = (char *) private_data;
160 : int ret;
161 :
162 0 : ret = remove_krb5_info_files(se, realm);
163 0 : if (ret != EOK) {
164 0 : DEBUG(SSSDBG_CRIT_FAILURE, "remove_krb5_info_files failed.\n");
165 : }
166 :
167 0 : orderly_shutdown(0);
168 0 : }
169 :
170 0 : errno_t sdap_install_sigterm_handler(TALLOC_CTX *mem_ctx,
171 : struct tevent_context *ev,
172 : const char *realm)
173 : {
174 : char *sig_realm;
175 : struct tevent_signal *sige;
176 :
177 0 : BlockSignals(false, SIGTERM);
178 :
179 0 : sig_realm = talloc_strdup(mem_ctx, realm);
180 0 : if (sig_realm == NULL) {
181 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed!\n");
182 0 : return ENOMEM;
183 : }
184 :
185 0 : sige = tevent_add_signal(ev, mem_ctx, SIGTERM, SA_SIGINFO, sdap_finalize,
186 : sig_realm);
187 0 : if (sige == NULL) {
188 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_signal failed.\n");
189 0 : talloc_free(sig_realm);
190 0 : return ENOMEM;
191 : }
192 0 : talloc_steal(sige, sig_realm);
193 :
194 0 : return EOK;
195 : }
196 :
197 0 : void sdap_remove_kdcinfo_files_callback(void *pvt)
198 : {
199 : int ret;
200 0 : TALLOC_CTX *tmp_ctx = NULL;
201 0 : struct remove_info_files_ctx *ctx = talloc_get_type(pvt,
202 : struct remove_info_files_ctx);
203 :
204 0 : ret = be_fo_run_callbacks_at_next_request(ctx->be_ctx,
205 : ctx->kdc_service_name);
206 0 : if (ret != EOK) {
207 0 : DEBUG(SSSDBG_CRIT_FAILURE,
208 : "be_fo_run_callbacks_at_next_request failed, "
209 : "krb5 info files will not be removed, because "
210 : "it is unclear if they will be recreated properly.\n");
211 0 : return;
212 : }
213 :
214 0 : tmp_ctx = talloc_new(NULL);
215 0 : if (tmp_ctx == NULL) {
216 0 : DEBUG(SSSDBG_CRIT_FAILURE,
217 : "talloc_new failed, cannot remove krb5 info files.\n");
218 0 : return;
219 : }
220 :
221 0 : ret = remove_krb5_info_files(tmp_ctx, ctx->realm);
222 0 : if (ret != EOK) {
223 0 : DEBUG(SSSDBG_CRIT_FAILURE, "remove_krb5_info_files failed.\n");
224 : }
225 :
226 0 : talloc_zfree(tmp_ctx);
227 : }
228 :
229 :
230 0 : errno_t sdap_install_offline_callback(TALLOC_CTX *mem_ctx,
231 : struct be_ctx *be_ctx,
232 : const char *realm,
233 : const char *service_name)
234 : {
235 : int ret;
236 : struct remove_info_files_ctx *ctx;
237 :
238 0 : ctx = talloc_zero(mem_ctx, struct remove_info_files_ctx);
239 0 : if (ctx == NULL) {
240 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zfree failed.\n");
241 0 : return ENOMEM;
242 : }
243 :
244 0 : ctx->be_ctx = be_ctx;
245 0 : ctx->realm = talloc_strdup(ctx, realm);
246 0 : ctx->kdc_service_name = talloc_strdup(ctx, service_name);
247 0 : if (ctx->realm == NULL || ctx->kdc_service_name == NULL) {
248 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed!\n");
249 0 : ret = ENOMEM;
250 0 : goto done;
251 : }
252 :
253 0 : ret = be_add_offline_cb(ctx, be_ctx,
254 : sdap_remove_kdcinfo_files_callback,
255 : ctx, NULL);
256 0 : if (ret != EOK) {
257 0 : DEBUG(SSSDBG_CRIT_FAILURE, "be_add_offline_cb failed.\n");
258 0 : goto done;
259 : }
260 :
261 0 : ret = EOK;
262 : done:
263 0 : if (ret != EOK) {
264 0 : talloc_zfree(ctx);
265 : }
266 0 : return ret;
267 : }
268 :
269 : errno_t
270 0 : sdap_set_sasl_options(struct sdap_options *id_opts,
271 : char *default_primary,
272 : char *default_realm,
273 : const char *keytab_path)
274 : {
275 : errno_t ret;
276 : TALLOC_CTX *tmp_ctx;
277 : char *sasl_primary;
278 : char *desired_primary;
279 : char *primary_realm;
280 : char *sasl_realm;
281 : char *desired_realm;
282 0 : bool primary_requested = true;
283 0 : bool realm_requested = true;
284 :
285 0 : tmp_ctx = talloc_new(NULL);
286 0 : if (!tmp_ctx) return ENOMEM;
287 :
288 : /* Configuration of SASL auth ID and realm */
289 0 : desired_primary = dp_opt_get_string(id_opts->basic, SDAP_SASL_AUTHID);
290 0 : if (!desired_primary) {
291 0 : primary_requested = false;
292 0 : desired_primary = default_primary;
293 : }
294 :
295 0 : if ((primary_realm = strchr(desired_primary, '@'))) {
296 0 : *primary_realm = '\0';
297 0 : desired_realm = primary_realm+1;
298 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
299 : "authid contains realm [%s]\n", desired_realm);
300 : } else {
301 0 : desired_realm = dp_opt_get_string(id_opts->basic, SDAP_SASL_REALM);
302 0 : if (!desired_realm) {
303 0 : realm_requested = false;
304 0 : desired_realm = default_realm;
305 : }
306 : }
307 :
308 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Will look for %s@%s in %s\n",
309 : desired_primary, desired_realm,
310 : keytab_path ? keytab_path : "default keytab");
311 :
312 0 : ret = select_principal_from_keytab(tmp_ctx,
313 : desired_primary, desired_realm,
314 : keytab_path,
315 : NULL, &sasl_primary, &sasl_realm);
316 0 : if (ret != EOK) {
317 0 : goto done;
318 : }
319 :
320 0 : if (primary_requested && strcmp(desired_primary, sasl_primary) != 0) {
321 0 : DEBUG(SSSDBG_MINOR_FAILURE,
322 : "Configured SASL auth ID not found in keytab. "
323 : "Requested %s, found %s\n", desired_primary, sasl_primary);
324 : }
325 :
326 0 : if (realm_requested && strcmp(desired_realm, sasl_realm) != 0) {
327 0 : DEBUG(SSSDBG_MINOR_FAILURE,
328 : "Configured SASL realm not found in keytab. "
329 : "Requested %s, found %s\n", desired_realm, sasl_realm);
330 : }
331 :
332 0 : ret = dp_opt_set_string(id_opts->basic,
333 : SDAP_SASL_AUTHID, sasl_primary);
334 0 : if (ret != EOK) {
335 0 : goto done;
336 : }
337 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Option %s set to %s\n",
338 : id_opts->basic[SDAP_SASL_AUTHID].opt_name,
339 : dp_opt_get_string(id_opts->basic, SDAP_SASL_AUTHID));
340 :
341 0 : ret = dp_opt_set_string(id_opts->basic,
342 : SDAP_SASL_REALM, sasl_realm);
343 0 : if (ret != EOK) {
344 0 : goto done;
345 : }
346 :
347 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Option %s set to %s\n",
348 : id_opts->basic[SDAP_SASL_REALM].opt_name,
349 : dp_opt_get_string(id_opts->basic, SDAP_SASL_REALM));
350 :
351 0 : ret = EOK;
352 : done:
353 0 : talloc_free(tmp_ctx);
354 0 : return ret;
355 : }
356 :
357 : static const char *
358 0 : sdap_gssapi_get_default_realm(TALLOC_CTX *mem_ctx)
359 : {
360 0 : char *krb5_realm = NULL;
361 0 : const char *realm = NULL;
362 : krb5_error_code krberr;
363 0 : krb5_context context = NULL;
364 :
365 0 : krberr = krb5_init_context(&context);
366 0 : if (krberr) {
367 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to init kerberos context\n");
368 0 : goto done;
369 : }
370 :
371 0 : krberr = krb5_get_default_realm(context, &krb5_realm);
372 0 : if (krberr) {
373 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to get default realm name: %s\n",
374 : sss_krb5_get_error_message(context, krberr));
375 0 : goto done;
376 : }
377 :
378 0 : realm = talloc_strdup(mem_ctx, krb5_realm);
379 0 : krb5_free_default_realm(context, krb5_realm);
380 0 : if (!realm) {
381 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory\n");
382 0 : goto done;
383 : }
384 :
385 0 : DEBUG(SSSDBG_TRACE_LIBS, "Will use default realm %s\n", realm);
386 : done:
387 0 : if (context) krb5_free_context(context);
388 0 : return realm;
389 : }
390 :
391 0 : const char *sdap_gssapi_realm(struct dp_option *opts)
392 : {
393 : const char *realm;
394 :
395 0 : realm = dp_opt_get_cstring(opts, SDAP_SASL_REALM);
396 0 : if (!realm) {
397 0 : realm = dp_opt_get_cstring(opts, SDAP_KRB5_REALM);
398 : }
399 :
400 0 : return realm;
401 : }
402 :
403 0 : int sdap_gssapi_init(TALLOC_CTX *mem_ctx,
404 : struct dp_option *opts,
405 : struct be_ctx *bectx,
406 : struct sdap_service *sdap_service,
407 : struct krb5_service **krb5_service)
408 : {
409 : int ret;
410 : const char *krb5_servers;
411 : const char *krb5_backup_servers;
412 : const char *krb5_realm;
413 : const char *krb5_opt_realm;
414 0 : struct krb5_service *service = NULL;
415 : TALLOC_CTX *tmp_ctx;
416 :
417 0 : tmp_ctx = talloc_new(NULL);
418 0 : if (tmp_ctx == NULL) return ENOMEM;
419 :
420 0 : krb5_servers = dp_opt_get_string(opts, SDAP_KRB5_KDC);
421 0 : krb5_backup_servers = dp_opt_get_string(opts, SDAP_KRB5_BACKUP_KDC);
422 :
423 0 : krb5_opt_realm = sdap_gssapi_realm(opts);
424 0 : if (krb5_opt_realm == NULL) {
425 0 : DEBUG(SSSDBG_OP_FAILURE,
426 : "Missing krb5_realm option, will use libkrb default\n");
427 0 : krb5_realm = sdap_gssapi_get_default_realm(tmp_ctx);
428 0 : if (krb5_realm == NULL) {
429 0 : DEBUG(SSSDBG_FATAL_FAILURE,
430 : "Cannot determine the Kerberos realm, aborting\n");
431 0 : ret = EIO;
432 0 : goto done;
433 : }
434 : } else {
435 0 : krb5_realm = talloc_strdup(tmp_ctx, krb5_opt_realm);
436 0 : if (krb5_realm == NULL) {
437 0 : ret = ENOMEM;
438 0 : goto done;
439 : }
440 : }
441 :
442 0 : ret = krb5_service_init(mem_ctx, bectx,
443 : SSS_KRB5KDC_FO_SRV, krb5_servers,
444 : krb5_backup_servers, krb5_realm,
445 0 : dp_opt_get_bool(opts,
446 : SDAP_KRB5_USE_KDCINFO),
447 : &service);
448 0 : if (ret != EOK) {
449 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init KRB5 failover service!\n");
450 0 : goto done;
451 : }
452 :
453 0 : ret = sdap_install_sigterm_handler(mem_ctx, bectx->ev, krb5_realm);
454 0 : if (ret != EOK) {
455 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to install sigterm handler\n");
456 0 : goto done;
457 : }
458 :
459 0 : ret = sdap_install_offline_callback(mem_ctx, bectx,
460 : krb5_realm, SSS_KRB5KDC_FO_SRV);
461 0 : if (ret != EOK) {
462 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to install sigterm handler\n");
463 0 : goto done;
464 : }
465 :
466 0 : sdap_service->kinit_service_name = talloc_strdup(sdap_service,
467 0 : service->name);
468 0 : if (sdap_service->kinit_service_name == NULL) {
469 0 : ret = ENOMEM;
470 0 : goto done;
471 : }
472 :
473 0 : ret = EOK;
474 0 : *krb5_service = service;
475 : done:
476 0 : talloc_free(tmp_ctx);
477 0 : if (ret != EOK) talloc_free(service);
478 0 : return ret;
479 : }
480 :
481 0 : static errno_t _sdap_urls_init(struct be_ctx *ctx,
482 : struct sdap_service *service,
483 : const char *service_name,
484 : const char *dns_service_name,
485 : const char *urls,
486 : bool primary)
487 : {
488 : TALLOC_CTX *tmp_ctx;
489 : char *srv_user_data;
490 0 : char **list = NULL;
491 : LDAPURLDesc *lud;
492 0 : errno_t ret = 0;
493 : int i;
494 :
495 0 : tmp_ctx = talloc_new(NULL);
496 0 : if (!tmp_ctx) {
497 0 : return ENOMEM;
498 : }
499 :
500 :
501 : /* split server parm into a list */
502 0 : ret = split_on_separator(tmp_ctx, urls, ',', true, true, &list, NULL);
503 0 : if (ret != EOK) {
504 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse server list!\n");
505 0 : goto done;
506 : }
507 :
508 : /* now for each URI add a new server to the failover service */
509 0 : for (i = 0; list[i]; i++) {
510 0 : if (be_fo_is_srv_identifier(list[i])) {
511 0 : if (!primary) {
512 0 : DEBUG(SSSDBG_MINOR_FAILURE,
513 : "Failed to add server [%s] to failover service: "
514 : "SRV resolution only allowed for primary servers!\n",
515 : list[i]);
516 0 : continue;
517 : }
518 :
519 0 : if (!dns_service_name) {
520 0 : DEBUG(SSSDBG_FATAL_FAILURE,
521 : "Missing DNS service name for service [%s].\n",
522 : service_name);
523 0 : ret = EINVAL;
524 0 : goto done;
525 : }
526 0 : srv_user_data = talloc_strdup(service, dns_service_name);
527 0 : if (!srv_user_data) {
528 0 : ret = ENOMEM;
529 0 : goto done;
530 : }
531 :
532 0 : ret = be_fo_add_srv_server(ctx, service_name,
533 : dns_service_name, NULL,
534 : BE_FO_PROTO_TCP, false, srv_user_data);
535 0 : if (ret) {
536 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add server\n");
537 0 : goto done;
538 : }
539 :
540 0 : DEBUG(SSSDBG_TRACE_FUNC, "Added service lookup\n");
541 0 : continue;
542 : }
543 :
544 0 : ret = ldap_url_parse(list[i], &lud);
545 0 : if (ret != LDAP_SUCCESS) {
546 0 : DEBUG(SSSDBG_FATAL_FAILURE,
547 : "Failed to parse ldap URI (%s)!\n", list[i]);
548 0 : ret = EINVAL;
549 0 : goto done;
550 : }
551 :
552 0 : if (lud->lud_host == NULL) {
553 0 : DEBUG(SSSDBG_OP_FAILURE,
554 : "The LDAP URI (%s) did not contain a host name\n",
555 : list[i]);
556 0 : ldap_free_urldesc(lud);
557 0 : continue;
558 : }
559 :
560 0 : DEBUG(SSSDBG_TRACE_FUNC, "Added URI %s\n", list[i]);
561 :
562 0 : talloc_steal(service, list[i]);
563 :
564 : /* It could be ipv6 address in square brackets. Remove
565 : * the brackets if needed. */
566 0 : ret = remove_ipv6_brackets(lud->lud_host);
567 0 : if (ret != EOK) {
568 0 : goto done;
569 : }
570 :
571 0 : ret = be_fo_add_server(ctx, service->name, lud->lud_host,
572 0 : lud->lud_port, list[i], primary);
573 0 : ldap_free_urldesc(lud);
574 0 : if (ret) {
575 0 : goto done;
576 : }
577 : }
578 :
579 : done:
580 0 : talloc_free(tmp_ctx);
581 0 : return ret;
582 : }
583 :
584 :
585 : static inline errno_t
586 0 : sdap_primary_urls_init(struct be_ctx *ctx, struct sdap_service *service,
587 : const char *service_name, const char *dns_service_name,
588 : const char *urls)
589 : {
590 0 : return _sdap_urls_init(ctx, service, service_name,
591 : dns_service_name, urls, true);
592 : }
593 :
594 : static inline errno_t
595 0 : sdap_backup_urls_init(struct be_ctx *ctx, struct sdap_service *service,
596 : const char *service_name, const char *dns_service_name,
597 : const char *urls)
598 : {
599 0 : return _sdap_urls_init(ctx, service, service_name,
600 : dns_service_name, urls, false);
601 : }
602 :
603 0 : static int ldap_user_data_cmp(void *ud1, void *ud2)
604 : {
605 0 : return strcasecmp((char*) ud1, (char*) ud2);
606 : }
607 :
608 0 : int sdap_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
609 : const char *service_name, const char *dns_service_name,
610 : const char *urls, const char *backup_urls,
611 : struct sdap_service **_service)
612 : {
613 : TALLOC_CTX *tmp_ctx;
614 : struct sdap_service *service;
615 : int ret;
616 :
617 0 : tmp_ctx = talloc_new(NULL);
618 0 : if (!tmp_ctx) {
619 0 : return ENOMEM;
620 : }
621 :
622 0 : service = talloc_zero(tmp_ctx, struct sdap_service);
623 0 : if (!service) {
624 0 : ret = ENOMEM;
625 0 : goto done;
626 : }
627 :
628 0 : ret = be_fo_add_service(ctx, service_name, ldap_user_data_cmp);
629 0 : if (ret != EOK) {
630 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create failover service!\n");
631 0 : goto done;
632 : }
633 :
634 0 : service->name = talloc_strdup(service, service_name);
635 0 : if (!service->name) {
636 0 : ret = ENOMEM;
637 0 : goto done;
638 : }
639 :
640 0 : if (!urls) {
641 0 : DEBUG(SSSDBG_CONF_SETTINGS,
642 : "No primary servers defined, using service discovery\n");
643 0 : urls = BE_SRV_IDENTIFIER;
644 : }
645 :
646 0 : ret = sdap_primary_urls_init(ctx, service, service_name, dns_service_name,
647 : urls);
648 0 : if (ret != EOK) {
649 0 : goto done;
650 : }
651 :
652 0 : if (backup_urls) {
653 0 : ret = sdap_backup_urls_init(ctx, service, service_name,
654 : dns_service_name, backup_urls);
655 0 : if (ret != EOK) {
656 0 : goto done;
657 : }
658 : }
659 :
660 0 : ret = be_fo_service_add_callback(memctx, ctx, service->name,
661 : sdap_uri_callback, service);
662 0 : if (ret != EOK) {
663 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to add failover callback!\n");
664 0 : goto done;
665 : }
666 :
667 0 : ret = EOK;
668 :
669 : done:
670 0 : if (ret == EOK) {
671 0 : *_service = talloc_steal(memctx, service);
672 : }
673 0 : talloc_zfree(tmp_ctx);
674 0 : return ret;
675 : }
676 :
677 0 : errno_t string_to_shadowpw_days(const char *s, long *d)
678 : {
679 : long l;
680 : char *endptr;
681 :
682 0 : if (s == NULL || *s == '\0') {
683 0 : *d = -1;
684 0 : return EOK;
685 : }
686 :
687 0 : errno = 0;
688 0 : l = strtol(s, &endptr, 10);
689 0 : if (errno != 0) {
690 0 : DEBUG(SSSDBG_CRIT_FAILURE,
691 : "strtol failed [%d][%s].\n", errno, strerror(errno));
692 0 : return errno;
693 : }
694 :
695 0 : if (*endptr != '\0') {
696 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Input string [%s] is invalid.\n", s);
697 0 : return EINVAL;
698 : }
699 :
700 0 : if (l < -1) {
701 0 : DEBUG(SSSDBG_CRIT_FAILURE,
702 : "Input string contains not allowed negative value [%ld].\n",
703 : l);
704 0 : return EINVAL;
705 : }
706 :
707 0 : *d = l;
708 :
709 0 : return EOK;
710 : }
711 :
712 0 : errno_t get_sysdb_attr_name(TALLOC_CTX *mem_ctx,
713 : struct sdap_attr_map *map,
714 : size_t map_size,
715 : const char *ldap_name,
716 : char **sysdb_name)
717 : {
718 : size_t i;
719 :
720 0 : for (i = 0; i < map_size; i++) {
721 : /* Skip map entries with no name (may depend on
722 : * schema selected)
723 : */
724 0 : if (!map[i].name) continue;
725 :
726 : /* Check if it is a mapped attribute */
727 0 : if(strcasecmp(ldap_name, map[i].name) == 0) break;
728 : }
729 :
730 0 : if (i < map_size) {
731 : /* We found a mapped name, return that */
732 0 : *sysdb_name = talloc_strdup(mem_ctx, map[i].sys_name);
733 : } else {
734 : /* Not mapped, use the same name */
735 0 : *sysdb_name = talloc_strdup(mem_ctx, ldap_name);
736 : }
737 :
738 0 : if (!*sysdb_name) {
739 0 : return ENOMEM;
740 : }
741 :
742 0 : return EOK;
743 : }
744 :
745 0 : errno_t list_missing_attrs(TALLOC_CTX *mem_ctx,
746 : struct sdap_attr_map *map,
747 : size_t map_size,
748 : struct sysdb_attrs *recvd_attrs,
749 : char ***missing_attrs)
750 : {
751 : errno_t ret;
752 0 : size_t attr_count = 0;
753 : size_t i, j, k;
754 0 : char **missing = NULL;
755 : const char **expected_attrs;
756 : char *sysdb_name;
757 : TALLOC_CTX *tmp_ctx;
758 :
759 0 : if (!recvd_attrs || !missing_attrs) {
760 0 : return EINVAL;
761 : }
762 :
763 0 : tmp_ctx = talloc_new(NULL);
764 0 : if (!tmp_ctx) {
765 0 : return ENOMEM;
766 : }
767 :
768 0 : ret = build_attrs_from_map(tmp_ctx, map, map_size, NULL,
769 : &expected_attrs, &attr_count);
770 0 : if (ret != EOK) {
771 0 : goto done;
772 : }
773 :
774 : /* Allocate the maximum possible values for missing_attrs, to
775 : * be on the safe side
776 : */
777 0 : missing = talloc_array(tmp_ctx, char *, attr_count + 2);
778 0 : if (!missing) {
779 0 : ret = ENOMEM;
780 0 : goto done;
781 : }
782 :
783 0 : k = 0;
784 : /* Check for each expected attribute */
785 0 : for (i = 0; i < attr_count; i++) {
786 0 : ret = get_sysdb_attr_name(tmp_ctx, map, map_size,
787 0 : expected_attrs[i],
788 : &sysdb_name);
789 0 : if (ret != EOK) {
790 0 : goto done;
791 : }
792 :
793 : /* objectClass is a special-case and we need to
794 : * check for it explicitly.
795 : */
796 0 : if (strcasecmp(sysdb_name, "objectClass") == 0) {
797 0 : talloc_free(sysdb_name);
798 0 : continue;
799 : }
800 :
801 : /* GECOS is another special case. Its value can come
802 : * either from the 'gecos' attribute or the 'cn'
803 : * attribute. It's best if we just never remove it.
804 : */
805 0 : if (strcasecmp(sysdb_name, SYSDB_GECOS) == 0) {
806 0 : talloc_free(sysdb_name);
807 0 : continue;
808 : }
809 :
810 0 : for (j = 0; j < recvd_attrs->num; j++) {
811 : /* Check whether this expected attribute appeared in the
812 : * received attributes and had a non-zero number of
813 : * values.
814 : */
815 0 : if ((strcasecmp(recvd_attrs->a[j].name, sysdb_name) == 0) &&
816 0 : (recvd_attrs->a[j].num_values > 0)) {
817 0 : break;
818 : }
819 : }
820 :
821 0 : if (j < recvd_attrs->num) {
822 : /* Attribute was found, therefore not missing */
823 0 : talloc_free(sysdb_name);
824 : } else {
825 : /* Attribute could not be found. Add to the missing list */
826 0 : missing[k] = talloc_steal(missing, sysdb_name);
827 0 : k++;
828 :
829 : /* Remove originalMemberOf as well if MemberOf is missing */
830 0 : if (strcmp(sysdb_name, SYSDB_MEMBEROF) == 0) {
831 0 : missing[k] = talloc_strdup(missing, SYSDB_ORIG_MEMBEROF);
832 0 : k++;
833 : }
834 : }
835 : }
836 :
837 0 : if (k == 0) {
838 0 : *missing_attrs = NULL;
839 : } else {
840 : /* Terminate the list */
841 0 : missing[k] = NULL;
842 0 : *missing_attrs = talloc_steal(mem_ctx, missing);
843 : }
844 0 : ret = EOK;
845 :
846 : done:
847 0 : talloc_free(tmp_ctx);
848 0 : return ret;
849 : }
850 :
851 0 : bool sdap_is_secure_uri(const char *uri)
852 : {
853 : /* LDAPS URI's are secure channels */
854 0 : if (strncasecmp(uri, LDAP_SSL_URI, strlen(LDAP_SSL_URI)) == 0) {
855 0 : return true;
856 : }
857 0 : return false;
858 : }
859 :
860 10 : char *sdap_get_access_filter(TALLOC_CTX *mem_ctx,
861 : const char *base_filter)
862 : {
863 10 : char *filter = NULL;
864 :
865 10 : if (base_filter == NULL) return NULL;
866 :
867 9 : if (base_filter[0] == '(') {
868 : /* This filter is wrapped in parentheses.
869 : * Pass it as-is to the openldap libraries.
870 : */
871 7 : filter = talloc_strdup(mem_ctx, base_filter);
872 : } else {
873 2 : filter = talloc_asprintf(mem_ctx, "(%s)", base_filter);
874 : }
875 :
876 9 : return filter;
877 : }
878 :
879 : errno_t
880 0 : sdap_attrs_get_sid_str(TALLOC_CTX *mem_ctx,
881 : struct sdap_idmap_ctx *idmap_ctx,
882 : struct sysdb_attrs *sysdb_attrs,
883 : const char *sid_attr,
884 : char **_sid_str)
885 : {
886 : errno_t ret;
887 : enum idmap_error_code err;
888 : struct ldb_message_element *el;
889 : char *sid_str;
890 :
891 0 : ret = sysdb_attrs_get_el(sysdb_attrs, sid_attr, &el);
892 0 : if (ret != EOK || el->num_values != 1) {
893 0 : DEBUG(SSSDBG_TRACE_LIBS,
894 : "No [%s] attribute. [%d][%s]\n",
895 : sid_attr, el->num_values, strerror(ret));
896 0 : return ENOENT;
897 : }
898 :
899 0 : if (el->values[0].length > 2 &&
900 0 : el->values[0].data[0] == 'S' &&
901 0 : el->values[0].data[1] == '-') {
902 0 : sid_str = talloc_strndup(mem_ctx, (char *) el->values[0].data,
903 0 : el->values[0].length);
904 0 : if (sid_str == NULL) {
905 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
906 0 : return ENOMEM;
907 : }
908 : } else {
909 0 : err = sss_idmap_bin_sid_to_sid(idmap_ctx->map,
910 0 : el->values[0].data,
911 0 : el->values[0].length,
912 : &sid_str);
913 0 : if (err != IDMAP_SUCCESS) {
914 0 : DEBUG(SSSDBG_MINOR_FAILURE,
915 : "Could not convert SID: [%s]\n",
916 : idmap_error_string(err));
917 0 : return EIO;
918 : }
919 : }
920 :
921 0 : *_sid_str = talloc_steal(mem_ctx, sid_str);
922 :
923 0 : return EOK;
924 : }
925 :
926 : struct sdap_id_conn_ctx *
927 0 : sdap_id_ctx_conn_add(struct sdap_id_ctx *id_ctx,
928 : struct sdap_service *sdap_service)
929 : {
930 : struct sdap_id_conn_ctx *conn;
931 : errno_t ret;
932 :
933 0 : conn = talloc_zero(id_ctx, struct sdap_id_conn_ctx);
934 0 : if (conn == NULL) {
935 0 : return NULL;
936 : }
937 0 : conn->service = talloc_steal(conn, sdap_service);
938 0 : conn->id_ctx = id_ctx;
939 :
940 : /* Create a connection cache */
941 0 : ret = sdap_id_conn_cache_create(conn, conn, &conn->conn_cache);
942 0 : if (ret != EOK) {
943 0 : talloc_free(conn);
944 0 : return NULL;
945 : }
946 0 : DLIST_ADD_END(id_ctx->conn, conn, struct sdap_id_conn_ctx *);
947 :
948 0 : return conn;
949 : }
950 :
951 : struct sdap_id_ctx *
952 0 : sdap_id_ctx_new(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
953 : struct sdap_service *sdap_service)
954 : {
955 : struct sdap_id_ctx *sdap_ctx;
956 :
957 0 : sdap_ctx = talloc_zero(mem_ctx, struct sdap_id_ctx);
958 0 : if (sdap_ctx == NULL) {
959 0 : return NULL;
960 : }
961 0 : sdap_ctx->be = bectx;
962 :
963 : /* There should be at least one connection context */
964 0 : sdap_ctx->conn = sdap_id_ctx_conn_add(sdap_ctx, sdap_service);
965 0 : if (sdap_ctx->conn == NULL) {
966 0 : talloc_free(sdap_ctx);
967 0 : return NULL;
968 : }
969 :
970 0 : return sdap_ctx;
971 : }
|