docs-xml: Fix rid idmap backend documentation
[Samba.git] / source3 / winbindd / idmap_rfc2307.c
blob2b3223829e2e36d98283249c7a329ad95c46bffa
1 /*
2 * Unix SMB/CIFS implementation.
4 * Id mapping using LDAP records as defined in RFC 2307
6 * The SID<->uid/gid mapping is performed in two steps: 1) Query the
7 * AD server for the name<->sid mapping. 2) Query an LDAP server
8 * according to RFC 2307 for the name<->uid/gid mapping.
10 * Copyright (C) Christof Schmitt 2012,2013
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "winbindd.h"
28 #include "winbindd_ads.h"
29 #include "idmap.h"
30 #include "smbldap.h"
31 #include "nsswitch/winbind_client.h"
32 #include "lib/winbind_util.h"
33 #include "libcli/security/dom_sid.h"
34 #include "lib/global_contexts.h"
37 * Config and connection info per domain.
39 struct idmap_rfc2307_context {
40 const char *bind_path_user;
41 const char *bind_path_group;
42 const char *ldap_domain;
43 bool user_cn;
44 const char *realm;
47 * Pointer to ldap struct in ads or smbldap_state, has to be
48 * updated after connecting to server
50 LDAP *ldap;
52 /* Optional function to check connection to server */
53 NTSTATUS (*check_connection)(struct idmap_domain *dom);
55 /* Issue ldap query */
56 NTSTATUS (*search)(struct idmap_rfc2307_context *ctx,
57 const char *bind_path, const char *expr,
58 const char **attrs, LDAPMessage **res);
60 /* Access to LDAP in AD server */
61 ADS_STRUCT *ads;
63 /* Access to stand-alone LDAP server */
64 struct smbldap_state *smbldap_state;
68 * backend functions for LDAP queries through ADS
71 static NTSTATUS idmap_rfc2307_ads_check_connection(struct idmap_domain *dom)
73 struct idmap_rfc2307_context *ctx;
74 const char *dom_name = dom->name;
75 ADS_STATUS status;
77 DEBUG(10, ("ad_idmap_cached_connection: called for domain '%s'\n",
78 dom->name));
80 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
81 dom_name = ctx->ldap_domain ? ctx->ldap_domain : dom->name;
83 status = ads_idmap_cached_connection(dom_name, ctx, &ctx->ads);
84 if (ADS_ERR_OK(status)) {
85 ctx->ldap = ctx->ads->ldap.ld;
86 } else {
87 DEBUG(1, ("Could not connect to domain %s: %s\n", dom->name,
88 ads_errstr(status)));
91 return ads_ntstatus(status);
94 static NTSTATUS idmap_rfc2307_ads_search(struct idmap_rfc2307_context *ctx,
95 const char *bind_path,
96 const char *expr,
97 const char **attrs,
98 LDAPMessage **result)
100 ADS_STATUS status;
102 status = ads_do_search_retry(ctx->ads, bind_path,
103 LDAP_SCOPE_SUBTREE, expr, attrs, result);
105 if (!ADS_ERR_OK(status)) {
106 return ads_ntstatus(status);
109 ctx->ldap = ctx->ads->ldap.ld;
110 return ads_ntstatus(status);
113 static NTSTATUS idmap_rfc2307_init_ads(struct idmap_rfc2307_context *ctx,
114 const char *domain_name)
116 const char *ldap_domain;
118 ctx->search = idmap_rfc2307_ads_search;
119 ctx->check_connection = idmap_rfc2307_ads_check_connection;
121 ldap_domain = idmap_config_const_string(domain_name, "ldap_domain",
122 NULL);
123 if (ldap_domain) {
124 ctx->ldap_domain = talloc_strdup(ctx, ldap_domain);
125 if (ctx->ldap_domain == NULL) {
126 return NT_STATUS_NO_MEMORY;
130 return NT_STATUS_OK;
134 * backend function for LDAP queries through stand-alone LDAP server
137 static NTSTATUS idmap_rfc2307_ldap_search(struct idmap_rfc2307_context *ctx,
138 const char *bind_path,
139 const char *expr,
140 const char **attrs,
141 LDAPMessage **result)
143 int ret;
145 ret = smbldap_search(ctx->smbldap_state, bind_path, LDAP_SCOPE_SUBTREE,
146 expr, attrs, 0, result);
147 ctx->ldap = smbldap_get_ldap(ctx->smbldap_state);
149 if (ret == LDAP_SUCCESS) {
150 return NT_STATUS_OK;
153 return NT_STATUS_LDAP(ret);
156 static bool idmap_rfc2307_get_uint32(LDAP *ldap, LDAPMessage *entry,
157 const char *field, uint32_t *value)
159 bool b;
160 char str[20];
162 b = smbldap_get_single_attribute(ldap, entry, field, str, sizeof(str));
164 if (b) {
165 *value = atoi(str);
168 return b;
171 static NTSTATUS idmap_rfc2307_init_ldap(struct idmap_rfc2307_context *ctx,
172 const char *domain_name)
174 NTSTATUS ret;
175 char *url;
176 char *secret = NULL;
177 const char *ldap_url, *user_dn;
178 TALLOC_CTX *mem_ctx = ctx;
180 ldap_url = idmap_config_const_string(domain_name, "ldap_url", NULL);
181 if (!ldap_url) {
182 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
183 return NT_STATUS_UNSUCCESSFUL;
186 url = talloc_strdup(talloc_tos(), ldap_url);
188 user_dn = idmap_config_const_string(domain_name, "ldap_user_dn", NULL);
189 if (user_dn) {
190 secret = idmap_fetch_secret("ldap", domain_name, user_dn);
191 if (!secret) {
192 ret = NT_STATUS_ACCESS_DENIED;
193 goto done;
197 /* assume anonymous if we don't have a specified user */
198 ret = smbldap_init(mem_ctx, global_event_context(), url,
199 (user_dn == NULL), user_dn, secret,
200 &ctx->smbldap_state);
201 BURN_FREE_STR(secret);
202 if (!NT_STATUS_IS_OK(ret)) {
203 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", url));
204 goto done;
207 ctx->search = idmap_rfc2307_ldap_search;
209 done:
210 talloc_free(url);
211 return ret;
215 * common code for stand-alone LDAP and ADS
218 static void idmap_rfc2307_map_sid_results(struct idmap_rfc2307_context *ctx,
219 TALLOC_CTX *mem_ctx,
220 struct id_map **ids,
221 LDAPMessage *result,
222 const char *dom_name,
223 const char **attrs, int type)
225 int count, i;
226 LDAPMessage *entry;
228 count = ldap_count_entries(ctx->ldap, result);
230 for (i = 0; i < count; i++) {
231 char *name;
232 struct dom_sid sid;
233 enum lsa_SidType lsa_type;
234 struct id_map *map;
235 uint32_t id;
236 bool b;
238 if (i == 0) {
239 entry = ldap_first_entry(ctx->ldap, result);
240 } else {
241 entry = ldap_next_entry(ctx->ldap, entry);
243 if (!entry) {
244 DEBUG(2, ("Unable to fetch entry.\n"));
245 break;
248 name = smbldap_talloc_single_attribute(ctx->ldap, entry,
249 attrs[0], mem_ctx);
250 if (!name) {
251 DEBUG(1, ("Could not get user name\n"));
252 continue;
255 b = idmap_rfc2307_get_uint32(ctx->ldap, entry, attrs[1], &id);
256 if (!b) {
257 DEBUG(1, ("Could not pull id for record %s\n", name));
258 continue;
261 map = idmap_find_map_by_id(ids, type, id);
262 if (!map) {
263 DEBUG(1, ("Could not find id %d, name %s\n", id, name));
264 continue;
267 if (ctx->realm != NULL) {
268 /* Strip @realm from user or group name */
269 char *delim;
271 delim = strchr(name, '@');
272 if (delim) {
273 *delim = '\0';
277 /* by default calls to winbindd are disabled
278 the following call will not recurse so this is safe */
279 (void)winbind_on();
280 /* Lookup name from PDC using lsa_lookup_names() */
281 b = winbind_lookup_name(dom_name, name, &sid, &lsa_type);
282 (void)winbind_off();
284 if (!b) {
285 DEBUG(1, ("SID lookup failed for id %d, %s\n",
286 id, name));
287 continue;
290 if (type == ID_TYPE_UID && lsa_type != SID_NAME_USER) {
291 DEBUG(1, ("Wrong type %d for user name %s\n",
292 type, name));
293 continue;
296 if (type == ID_TYPE_GID && lsa_type != SID_NAME_DOM_GRP &&
297 lsa_type != SID_NAME_ALIAS &&
298 lsa_type != SID_NAME_WKN_GRP) {
299 DEBUG(1, ("Wrong type %d for group name %s\n",
300 type, name));
301 continue;
304 map->status = ID_MAPPED;
305 sid_copy(map->sid, &sid);
310 * Map unixids to names and then to sids.
312 static NTSTATUS idmap_rfc2307_unixids_to_sids(struct idmap_domain *dom,
313 struct id_map **ids)
315 struct idmap_rfc2307_context *ctx;
316 char *fltr_usr = NULL, *fltr_grp = NULL;
317 TALLOC_CTX *mem_ctx;
318 int cnt_usr = 0, cnt_grp = 0, idx = 0, bidx = 0;
319 LDAPMessage *result = NULL;
320 NTSTATUS ret;
322 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
323 mem_ctx = talloc_new(ctx);
324 if (!mem_ctx) {
325 return NT_STATUS_NO_MEMORY;
328 if (ctx->check_connection) {
329 ret = ctx->check_connection(dom);
330 if (!NT_STATUS_IS_OK(ret)) {
331 goto out;
335 again:
336 bidx = idx;
338 if (!fltr_usr) {
339 /* prepare new user query, see getpwuid() in RFC2307 */
340 fltr_usr = talloc_asprintf(mem_ctx,
341 "(&(objectClass=posixAccount)(|");
344 if (!fltr_grp) {
345 /* prepare new group query, see getgrgid() in RFC2307 */
346 fltr_grp = talloc_asprintf(mem_ctx,
347 "(&(objectClass=posixGroup)(|");
350 if (!fltr_usr || !fltr_grp) {
351 ret = NT_STATUS_NO_MEMORY;
352 goto out;
355 while (cnt_usr < IDMAP_LDAP_MAX_IDS &&
356 cnt_grp < IDMAP_LDAP_MAX_IDS && ids[idx]) {
358 switch (ids[idx]->xid.type) {
359 case ID_TYPE_UID:
360 fltr_usr = talloc_asprintf_append_buffer(fltr_usr,
361 "(uidNumber=%d)", ids[idx]->xid.id);
362 cnt_usr++;
363 break;
364 case ID_TYPE_GID:
365 fltr_grp = talloc_asprintf_append_buffer(fltr_grp,
366 "(gidNumber=%d)", ids[idx]->xid.id);
367 cnt_grp++;
368 break;
369 default:
370 DEBUG(3, ("Error: unknown ID type %d\n",
371 ids[idx]->xid.type));
372 ret = NT_STATUS_UNSUCCESSFUL;
373 goto out;
376 if (!fltr_usr || !fltr_grp) {
377 ret = NT_STATUS_NO_MEMORY;
378 goto out;
381 idx++;
384 if (cnt_usr == IDMAP_LDAP_MAX_IDS || (cnt_usr != 0 && !ids[idx])) {
385 const char *attrs[] = { NULL, /* uid or cn */
386 "uidNumber",
387 NULL };
389 fltr_usr = talloc_strdup_append(fltr_usr, "))");
390 if (!fltr_usr) {
391 ret = NT_STATUS_NO_MEMORY;
392 goto out;
395 attrs[0] = ctx->user_cn ? "cn" : "uid";
396 ret = ctx->search(ctx, ctx->bind_path_user, fltr_usr, attrs,
397 &result);
398 if (!NT_STATUS_IS_OK(ret)) {
399 goto out;
402 idmap_rfc2307_map_sid_results(ctx, mem_ctx, &ids[bidx], result,
403 dom->name, attrs, ID_TYPE_UID);
404 cnt_usr = 0;
405 TALLOC_FREE(fltr_usr);
408 if (cnt_grp == IDMAP_LDAP_MAX_IDS || (cnt_grp != 0 && !ids[idx])) {
409 const char *attrs[] = { "cn", "gidNumber", NULL };
411 fltr_grp = talloc_strdup_append(fltr_grp, "))");
412 if (!fltr_grp) {
413 ret = NT_STATUS_NO_MEMORY;
414 goto out;
416 ret = ctx->search(ctx, ctx->bind_path_group, fltr_grp, attrs,
417 &result);
418 if (!NT_STATUS_IS_OK(ret)) {
419 goto out;
422 idmap_rfc2307_map_sid_results(ctx, mem_ctx, &ids[bidx], result,
423 dom->name, attrs, ID_TYPE_GID);
424 cnt_grp = 0;
425 TALLOC_FREE(fltr_grp);
428 if (ids[idx]) {
429 goto again;
432 ret = NT_STATUS_OK;
434 out:
435 talloc_free(mem_ctx);
436 return ret;
439 struct idmap_rfc2307_map {
440 struct id_map *map;
441 const char *name;
442 enum id_type type;
446 * Lookup names for SIDS and store the data in the local mapping
447 * array.
449 static NTSTATUS idmap_rfc_2307_sids_to_names(TALLOC_CTX *mem_ctx,
450 struct id_map **ids,
451 struct idmap_rfc2307_map *maps,
452 struct idmap_rfc2307_context *ctx)
454 int i;
456 for (i = 0; ids[i]; i++) {
457 const char *domain, *name;
458 enum lsa_SidType lsa_type;
459 struct id_map *id = ids[i];
460 struct idmap_rfc2307_map *map = &maps[i];
461 struct dom_sid_buf buf;
462 bool b;
464 /* by default calls to winbindd are disabled
465 the following call will not recurse so this is safe */
466 (void)winbind_on();
467 b = winbind_lookup_sid(mem_ctx, ids[i]->sid, &domain, &name,
468 &lsa_type);
469 (void)winbind_off();
471 if (!b) {
472 DEBUG(1, ("Lookup sid %s failed.\n",
473 dom_sid_str_buf(ids[i]->sid, &buf)));
474 continue;
477 switch(lsa_type) {
478 case SID_NAME_USER:
479 id->xid.type = map->type = ID_TYPE_UID;
480 if (ctx->user_cn && ctx->realm != NULL) {
481 name = talloc_asprintf(mem_ctx, "%s@%s",
482 name, ctx->realm);
484 id->xid.type = map->type = ID_TYPE_UID;
485 break;
487 case SID_NAME_DOM_GRP:
488 case SID_NAME_ALIAS:
489 case SID_NAME_WKN_GRP:
490 if (ctx->realm != NULL) {
491 name = talloc_asprintf(mem_ctx, "%s@%s",
492 name, ctx->realm);
494 id->xid.type = map->type = ID_TYPE_GID;
495 break;
497 default:
498 DEBUG(1, ("Unknown lsa type %d for sid %s\n",
499 lsa_type,
500 dom_sid_str_buf(id->sid, &buf)));
501 id->status = ID_UNMAPPED;
502 continue;
505 map->map = id;
506 id->status = ID_UNKNOWN;
507 map->name = strupper_talloc(mem_ctx, name);
509 if (!map->name) {
510 return NT_STATUS_NO_MEMORY;
514 return NT_STATUS_OK;
518 * Find id_map entry by looking up the name in the internal
519 * mapping array.
521 static struct id_map* idmap_rfc2307_find_map(struct idmap_rfc2307_map *maps,
522 enum id_type type,
523 const char *name)
525 int i;
527 DEBUG(10, ("Looking for name %s, type %d\n", name, type));
529 for (i = 0; maps[i].map != NULL; i++) {
530 DEBUG(10, ("Entry %d: name %s, type %d\n",
531 i, maps[i].name, maps[i].type));
532 if (type == maps[i].type && strcmp(name, maps[i].name) == 0) {
533 return maps[i].map;
537 return NULL;
540 static void idmap_rfc2307_map_xid_results(struct idmap_rfc2307_context *ctx,
541 TALLOC_CTX *mem_ctx,
542 struct idmap_rfc2307_map *maps,
543 LDAPMessage *result,
544 struct idmap_domain *dom,
545 const char **attrs, enum id_type type)
547 int count, i;
548 LDAPMessage *entry;
550 count = ldap_count_entries(ctx->ldap, result);
552 for (i = 0; i < count; i++) {
553 uint32_t id;
554 char *name;
555 bool b;
556 struct id_map *id_map;
558 if (i == 0) {
559 entry = ldap_first_entry(ctx->ldap, result);
560 } else {
561 entry = ldap_next_entry(ctx->ldap, entry);
563 if (!entry) {
564 DEBUG(2, ("Unable to fetch entry.\n"));
565 break;
568 name = smbldap_talloc_single_attribute(ctx->ldap, entry,
569 attrs[0], mem_ctx);
570 if (!name) {
571 DEBUG(1, ("Could not get user name\n"));
572 continue;
575 b = idmap_rfc2307_get_uint32(ctx->ldap, entry, attrs[1], &id);
576 if (!b) {
577 DEBUG(5, ("Could not pull id for record %s\n", name));
578 continue;
581 if (!idmap_unix_id_is_in_range(id, dom)) {
582 DEBUG(5, ("Requested id (%u) out of range (%u - %u).\n",
583 id, dom->low_id, dom->high_id));
584 continue;
587 if (!strupper_m(name)) {
588 DEBUG(5, ("Could not convert %s to uppercase\n", name));
589 continue;
591 id_map = idmap_rfc2307_find_map(maps, type, name);
592 if (!id_map) {
593 DEBUG(0, ("Could not find mapping entry for name %s\n",
594 name));
595 continue;
598 id_map->xid.id = id;
599 id_map->status = ID_MAPPED;
604 * Map sids to names and then to unixids.
606 static NTSTATUS idmap_rfc2307_sids_to_unixids(struct idmap_domain *dom,
607 struct id_map **ids)
609 struct idmap_rfc2307_context *ctx;
610 TALLOC_CTX *mem_ctx;
611 struct idmap_rfc2307_map *int_maps;
612 int cnt_usr = 0, cnt_grp = 0, idx = 0;
613 char *fltr_usr = NULL, *fltr_grp = NULL;
614 NTSTATUS ret;
615 int i;
617 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
618 mem_ctx = talloc_new(talloc_tos());
619 if (!mem_ctx) {
620 return NT_STATUS_NO_MEMORY;
623 if (ctx->check_connection) {
624 ret = ctx->check_connection(dom);
625 if (!NT_STATUS_IS_OK(ret)) {
626 goto out;
630 for (i = 0; ids[i]; i++);
631 int_maps = talloc_zero_array(mem_ctx, struct idmap_rfc2307_map, i);
632 if (!int_maps) {
633 ret = NT_STATUS_NO_MEMORY;
634 goto out;
637 ret = idmap_rfc_2307_sids_to_names(mem_ctx, ids, int_maps, ctx);
638 if (!NT_STATUS_IS_OK(ret)) {
639 goto out;
642 again:
643 if (!fltr_usr) {
644 /* prepare new user query, see getpwuid() in RFC2307 */
645 fltr_usr = talloc_asprintf(mem_ctx,
646 "(&(objectClass=posixAccount)(|");
649 if (!fltr_grp) {
650 /* prepare new group query, see getgrgid() in RFC2307 */
651 fltr_grp = talloc_asprintf(mem_ctx,
652 "(&(objectClass=posixGroup)(|");
655 if (!fltr_usr || !fltr_grp) {
656 ret = NT_STATUS_NO_MEMORY;
657 goto out;
660 while (cnt_usr < IDMAP_LDAP_MAX_IDS &&
661 cnt_grp < IDMAP_LDAP_MAX_IDS && ids[idx]) {
662 struct id_map *id = ids[idx];
663 struct idmap_rfc2307_map *map = &int_maps[idx];
665 switch(id->xid.type) {
666 case ID_TYPE_UID:
667 fltr_usr = talloc_asprintf_append_buffer(fltr_usr,
668 "(%s=%s)", (ctx->user_cn ? "cn" : "uid"),
669 map->name);
670 cnt_usr++;
671 break;
673 case ID_TYPE_GID:
674 fltr_grp = talloc_asprintf_append_buffer(fltr_grp,
675 "(cn=%s)", map->name);
676 cnt_grp++;
677 break;
679 default:
680 break;
683 if (!fltr_usr || !fltr_grp) {
684 ret = NT_STATUS_NO_MEMORY;
685 goto out;
688 idx++;
691 if (cnt_usr == IDMAP_LDAP_MAX_IDS || (cnt_usr != 0 && !ids[idx])) {
692 const char *attrs[] = { NULL, /* uid or cn */
693 "uidNumber",
694 NULL };
695 LDAPMessage *result;
697 fltr_usr = talloc_strdup_append(fltr_usr, "))");
698 if (!fltr_usr) {
699 ret = NT_STATUS_NO_MEMORY;
700 goto out;
703 attrs[0] = ctx->user_cn ? "cn" : "uid";
704 ret = ctx->search(ctx, ctx->bind_path_user, fltr_usr, attrs,
705 &result);
706 if (!NT_STATUS_IS_OK(ret)) {
707 goto out;
710 idmap_rfc2307_map_xid_results(ctx, mem_ctx, int_maps,
711 result, dom, attrs, ID_TYPE_UID);
713 cnt_usr = 0;
714 TALLOC_FREE(fltr_usr);
717 if (cnt_grp == IDMAP_LDAP_MAX_IDS || (cnt_grp != 0 && !ids[idx])) {
718 const char *attrs[] = {"cn", "gidNumber", NULL };
719 LDAPMessage *result;
721 fltr_grp = talloc_strdup_append(fltr_grp, "))");
722 if (!fltr_grp) {
723 ret = NT_STATUS_NO_MEMORY;
724 goto out;
727 ret = ctx->search(ctx, ctx->bind_path_group, fltr_grp, attrs,
728 &result);
729 if (!NT_STATUS_IS_OK(ret)) {
730 goto out;
733 idmap_rfc2307_map_xid_results(ctx, mem_ctx, int_maps, result,
734 dom, attrs, ID_TYPE_GID);
735 cnt_grp = 0;
736 TALLOC_FREE(fltr_grp);
739 if (ids[idx]) {
740 goto again;
743 ret = NT_STATUS_OK;
745 out:
746 talloc_free(mem_ctx);
747 return ret;
750 static int idmap_rfc2307_context_destructor(struct idmap_rfc2307_context *ctx)
752 TALLOC_FREE(ctx->ads);
754 if (ctx->smbldap_state != NULL) {
755 smbldap_free_struct(&ctx->smbldap_state);
758 return 0;
761 static NTSTATUS idmap_rfc2307_initialize(struct idmap_domain *domain)
763 struct idmap_rfc2307_context *ctx;
764 const char *bind_path_user, *bind_path_group, *ldap_server, *realm;
765 NTSTATUS status;
767 ctx = talloc_zero(domain, struct idmap_rfc2307_context);
768 if (ctx == NULL) {
769 return NT_STATUS_NO_MEMORY;
771 talloc_set_destructor(ctx, idmap_rfc2307_context_destructor);
773 bind_path_user = idmap_config_const_string(
774 domain->name, "bind_path_user", NULL);
775 if (bind_path_user == NULL) {
776 status = NT_STATUS_INVALID_PARAMETER;
777 goto err;
779 ctx->bind_path_user = talloc_strdup(ctx, bind_path_user);
780 if (ctx->bind_path_user == NULL) {
781 status = NT_STATUS_NO_MEMORY;
782 goto err;
785 bind_path_group = idmap_config_const_string(
786 domain->name, "bind_path_group", NULL);
787 if (bind_path_group == NULL) {
788 status = NT_STATUS_INVALID_PARAMETER;
789 goto err;
791 ctx->bind_path_group = talloc_strdup(ctx, bind_path_group);
792 if (ctx->bind_path_group == NULL) {
793 status = NT_STATUS_NO_MEMORY;
794 goto err;
797 ldap_server = idmap_config_const_string(
798 domain->name, "ldap_server", NULL);
799 if (!ldap_server) {
800 status = NT_STATUS_INVALID_PARAMETER;
801 goto err;
804 if (strcmp(ldap_server, "stand-alone") == 0) {
805 status = idmap_rfc2307_init_ldap(ctx, domain->name);
807 } else if (strcmp(ldap_server, "ad") == 0) {
808 status = idmap_rfc2307_init_ads(ctx, domain->name);
810 } else {
811 status = NT_STATUS_INVALID_PARAMETER;
814 if (!NT_STATUS_IS_OK(status)) {
815 goto err;
818 realm = idmap_config_const_string(domain->name, "realm", NULL);
819 if (realm) {
820 ctx->realm = talloc_strdup(ctx, realm);
821 if (ctx->realm == NULL) {
822 status = NT_STATUS_NO_MEMORY;
823 goto err;
827 ctx->user_cn = idmap_config_bool(domain->name, "user_cn", false);
829 domain->private_data = ctx;
830 return NT_STATUS_OK;
832 err:
833 talloc_free(ctx);
834 return status;
837 static const struct idmap_methods rfc2307_methods = {
838 .init = idmap_rfc2307_initialize,
839 .unixids_to_sids = idmap_rfc2307_unixids_to_sids,
840 .sids_to_unixids = idmap_rfc2307_sids_to_unixids,
843 static_decl_idmap;
844 NTSTATUS idmap_rfc2307_init(TALLOC_CTX *ctx)
846 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "rfc2307",
847 &rfc2307_methods);