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