winbind: Replace winbind_event_context with server_event_context
[Samba.git] / source3 / winbindd / idmap_rfc2307.c
blob264ccb034fb8c5838f0554d4ca409d584cb6ed33
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"
35 * Config and connection info per domain.
37 struct idmap_rfc2307_context {
38 const char *bind_path_user;
39 const char *bind_path_group;
40 const char *ldap_domain;
41 bool user_cn;
42 const char *realm;
45 * Pointer to ldap struct in ads or smbldap_state, has to be
46 * updated after connecting to server
48 LDAP *ldap;
50 /* Optional function to check connection to server */
51 NTSTATUS (*check_connection)(struct idmap_domain *dom);
53 /* Issue ldap query */
54 NTSTATUS (*search)(struct idmap_rfc2307_context *ctx,
55 const char *bind_path, const char *expr,
56 const char **attrs, LDAPMessage **res);
58 /* Access to LDAP in AD server */
59 ADS_STRUCT *ads;
61 /* Access to stand-alone LDAP server */
62 struct smbldap_state *smbldap_state;
66 * backend functions for LDAP queries through ADS
69 static NTSTATUS idmap_rfc2307_ads_check_connection(struct idmap_domain *dom)
71 struct idmap_rfc2307_context *ctx;
72 const char *dom_name = dom->name;
73 ADS_STATUS status;
75 DEBUG(10, ("ad_idmap_cached_connection: called for domain '%s'\n",
76 dom->name));
78 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
79 dom_name = ctx->ldap_domain ? ctx->ldap_domain : dom->name;
81 status = ads_idmap_cached_connection(&ctx->ads, dom_name);
82 if (ADS_ERR_OK(status)) {
83 ctx->ldap = ctx->ads->ldap.ld;
84 } else {
85 DEBUG(1, ("Could not connect to domain %s: %s\n", dom->name,
86 ads_errstr(status)));
89 return ads_ntstatus(status);
92 static NTSTATUS idmap_rfc2307_ads_search(struct idmap_rfc2307_context *ctx,
93 const char *bind_path,
94 const char *expr,
95 const char **attrs,
96 LDAPMessage **result)
98 ADS_STATUS status;
100 status = ads_do_search_retry(ctx->ads, bind_path,
101 LDAP_SCOPE_SUBTREE, expr, attrs, result);
103 if (!ADS_ERR_OK(status)) {
104 return ads_ntstatus(status);
107 ctx->ldap = ctx->ads->ldap.ld;
108 return ads_ntstatus(status);
111 static NTSTATUS idmap_rfc2307_init_ads(struct idmap_rfc2307_context *ctx,
112 const char *domain_name)
114 const char *ldap_domain;
116 ctx->search = idmap_rfc2307_ads_search;
117 ctx->check_connection = idmap_rfc2307_ads_check_connection;
119 ldap_domain = idmap_config_const_string(domain_name, "ldap_domain",
120 NULL);
121 if (ldap_domain) {
122 ctx->ldap_domain = talloc_strdup(ctx, ldap_domain);
123 if (ctx->ldap_domain == NULL) {
124 return NT_STATUS_NO_MEMORY;
128 return NT_STATUS_OK;
132 * backend function for LDAP queries through stand-alone LDAP server
135 static NTSTATUS idmap_rfc2307_ldap_search(struct idmap_rfc2307_context *ctx,
136 const char *bind_path,
137 const char *expr,
138 const char **attrs,
139 LDAPMessage **result)
141 int ret;
143 ret = smbldap_search(ctx->smbldap_state, bind_path, LDAP_SCOPE_SUBTREE,
144 expr, attrs, 0, result);
145 ctx->ldap = smbldap_get_ldap(ctx->smbldap_state);
147 if (ret == LDAP_SUCCESS) {
148 return NT_STATUS_OK;
151 return NT_STATUS_LDAP(ret);
154 static bool idmap_rfc2307_get_uint32(LDAP *ldap, LDAPMessage *entry,
155 const char *field, uint32_t *value)
157 bool b;
158 char str[20];
160 b = smbldap_get_single_attribute(ldap, entry, field, str, sizeof(str));
162 if (b) {
163 *value = atoi(str);
166 return b;
169 static NTSTATUS idmap_rfc2307_init_ldap(struct idmap_rfc2307_context *ctx,
170 const char *domain_name)
172 NTSTATUS ret;
173 char *url;
174 char *secret = NULL;
175 const char *ldap_url, *user_dn;
176 TALLOC_CTX *mem_ctx = ctx;
178 ldap_url = idmap_config_const_string(domain_name, "ldap_url", NULL);
179 if (!ldap_url) {
180 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
181 return NT_STATUS_UNSUCCESSFUL;
184 url = talloc_strdup(talloc_tos(), ldap_url);
186 user_dn = idmap_config_const_string(domain_name, "ldap_user_dn", NULL);
187 if (user_dn) {
188 secret = idmap_fetch_secret("ldap", domain_name, user_dn);
189 if (!secret) {
190 ret = NT_STATUS_ACCESS_DENIED;
191 goto done;
195 /* assume anonymous if we don't have a specified user */
196 ret = smbldap_init(mem_ctx, server_event_context(), url,
197 (user_dn == NULL), user_dn, secret,
198 &ctx->smbldap_state);
199 SAFE_FREE(secret);
200 if (!NT_STATUS_IS_OK(ret)) {
201 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", url));
202 goto done;
205 ctx->search = idmap_rfc2307_ldap_search;
207 done:
208 talloc_free(url);
209 return ret;
213 * common code for stand-alone LDAP and ADS
216 static void idmap_rfc2307_map_sid_results(struct idmap_rfc2307_context *ctx,
217 TALLOC_CTX *mem_ctx,
218 struct id_map **ids,
219 LDAPMessage *result,
220 const char *dom_name,
221 const char **attrs, int type)
223 int count, i;
224 LDAPMessage *entry;
226 count = ldap_count_entries(ctx->ldap, result);
228 for (i = 0; i < count; i++) {
229 char *name;
230 enum lsa_SidType lsa_type;
231 struct id_map *map;
232 uint32_t id;
233 bool b;
235 if (i == 0) {
236 entry = ldap_first_entry(ctx->ldap, result);
237 } else {
238 entry = ldap_next_entry(ctx->ldap, entry);
240 if (!entry) {
241 DEBUG(2, ("Unable to fetch entry.\n"));
242 break;
245 name = smbldap_talloc_single_attribute(ctx->ldap, entry,
246 attrs[0], mem_ctx);
247 if (!name) {
248 DEBUG(1, ("Could not get user name\n"));
249 continue;
252 b = idmap_rfc2307_get_uint32(ctx->ldap, entry, attrs[1], &id);
253 if (!b) {
254 DEBUG(1, ("Could not pull id for record %s\n", name));
255 continue;
258 map = idmap_find_map_by_id(ids, type, id);
259 if (!map) {
260 DEBUG(1, ("Could not find id %d, name %s\n", id, name));
261 continue;
264 if (ctx->realm != NULL) {
265 /* Strip @realm from user or group name */
266 char *delim;
268 delim = strchr(name, '@');
269 if (delim) {
270 *delim = '\0';
274 /* by default calls to winbindd are disabled
275 the following call will not recurse so this is safe */
276 (void)winbind_on();
277 /* Lookup name from PDC using lsa_lookup_names() */
278 b = winbind_lookup_name(dom_name, name, map->sid, &lsa_type);
279 (void)winbind_off();
281 if (!b) {
282 DEBUG(1, ("SID lookup failed for id %d, %s\n",
283 id, name));
284 continue;
287 if (type == ID_TYPE_UID && lsa_type != SID_NAME_USER) {
288 DEBUG(1, ("Wrong type %d for user name %s\n",
289 type, name));
290 continue;
293 if (type == ID_TYPE_GID && lsa_type != SID_NAME_DOM_GRP &&
294 lsa_type != SID_NAME_ALIAS &&
295 lsa_type != SID_NAME_WKN_GRP) {
296 DEBUG(1, ("Wrong type %d for group name %s\n",
297 type, name));
298 continue;
301 map->status = ID_MAPPED;
306 * Map unixids to names and then to sids.
308 static NTSTATUS idmap_rfc2307_unixids_to_sids(struct idmap_domain *dom,
309 struct id_map **ids)
311 struct idmap_rfc2307_context *ctx;
312 char *fltr_usr = NULL, *fltr_grp = NULL;
313 TALLOC_CTX *mem_ctx;
314 int cnt_usr = 0, cnt_grp = 0, idx = 0, bidx = 0;
315 LDAPMessage *result = NULL;
316 NTSTATUS ret;
318 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
319 mem_ctx = talloc_new(ctx);
320 if (!mem_ctx) {
321 return NT_STATUS_NO_MEMORY;
324 if (ctx->check_connection) {
325 ret = ctx->check_connection(dom);
326 if (!NT_STATUS_IS_OK(ret)) {
327 goto out;
331 again:
332 bidx = idx;
334 if (!fltr_usr) {
335 /* prepare new user query, see getpwuid() in RFC2307 */
336 fltr_usr = talloc_asprintf(mem_ctx,
337 "(&(objectClass=posixAccount)(|");
340 if (!fltr_grp) {
341 /* prepare new group query, see getgrgid() in RFC2307 */
342 fltr_grp = talloc_asprintf(mem_ctx,
343 "(&(objectClass=posixGroup)(|");
346 if (!fltr_usr || !fltr_grp) {
347 ret = NT_STATUS_NO_MEMORY;
348 goto out;
351 while (cnt_usr < IDMAP_LDAP_MAX_IDS &&
352 cnt_grp < IDMAP_LDAP_MAX_IDS && ids[idx]) {
354 switch (ids[idx]->xid.type) {
355 case ID_TYPE_UID:
356 fltr_usr = talloc_asprintf_append_buffer(fltr_usr,
357 "(uidNumber=%d)", ids[idx]->xid.id);
358 cnt_usr++;
359 break;
360 case ID_TYPE_GID:
361 fltr_grp = talloc_asprintf_append_buffer(fltr_grp,
362 "(gidNumber=%d)", ids[idx]->xid.id);
363 cnt_grp++;
364 break;
365 default:
366 DEBUG(3, ("Error: unknown ID type %d\n",
367 ids[idx]->xid.type));
368 ret = NT_STATUS_UNSUCCESSFUL;
369 goto out;
372 if (!fltr_usr || !fltr_grp) {
373 ret = NT_STATUS_NO_MEMORY;
374 goto out;
377 idx++;
380 if (cnt_usr == IDMAP_LDAP_MAX_IDS || (cnt_usr != 0 && !ids[idx])) {
381 const char *attrs[] = { NULL, /* uid or cn */
382 "uidNumber",
383 NULL };
385 fltr_usr = talloc_strdup_append(fltr_usr, "))");
386 if (!fltr_usr) {
387 ret = NT_STATUS_NO_MEMORY;
388 goto out;
391 attrs[0] = ctx->user_cn ? "cn" : "uid";
392 ret = ctx->search(ctx, ctx->bind_path_user, fltr_usr, attrs,
393 &result);
394 if (!NT_STATUS_IS_OK(ret)) {
395 goto out;
398 idmap_rfc2307_map_sid_results(ctx, mem_ctx, &ids[bidx], result,
399 dom->name, attrs, ID_TYPE_UID);
400 cnt_usr = 0;
401 TALLOC_FREE(fltr_usr);
404 if (cnt_grp == IDMAP_LDAP_MAX_IDS || (cnt_grp != 0 && !ids[idx])) {
405 const char *attrs[] = { "cn", "gidNumber", NULL };
407 fltr_grp = talloc_strdup_append(fltr_grp, "))");
408 if (!fltr_grp) {
409 ret = NT_STATUS_NO_MEMORY;
410 goto out;
412 ret = ctx->search(ctx, ctx->bind_path_group, fltr_grp, attrs,
413 &result);
414 if (!NT_STATUS_IS_OK(ret)) {
415 goto out;
418 idmap_rfc2307_map_sid_results(ctx, mem_ctx, &ids[bidx], result,
419 dom->name, attrs, ID_TYPE_GID);
420 cnt_grp = 0;
421 TALLOC_FREE(fltr_grp);
424 if (ids[idx]) {
425 goto again;
428 ret = NT_STATUS_OK;
430 out:
431 talloc_free(mem_ctx);
432 return ret;
435 struct idmap_rfc2307_map {
436 struct id_map *map;
437 const char *name;
438 enum id_type type;
442 * Lookup names for SIDS and store the data in the local mapping
443 * array.
445 static NTSTATUS idmap_rfc_2307_sids_to_names(TALLOC_CTX *mem_ctx,
446 struct id_map **ids,
447 struct idmap_rfc2307_map *maps,
448 struct idmap_rfc2307_context *ctx)
450 int i;
452 for (i = 0; ids[i]; i++) {
453 const char *domain, *name;
454 enum lsa_SidType lsa_type;
455 struct id_map *id = ids[i];
456 struct idmap_rfc2307_map *map = &maps[i];
457 bool b;
459 /* by default calls to winbindd are disabled
460 the following call will not recurse so this is safe */
461 (void)winbind_on();
462 b = winbind_lookup_sid(mem_ctx, ids[i]->sid, &domain, &name,
463 &lsa_type);
464 (void)winbind_off();
466 if (!b) {
467 DEBUG(1, ("Lookup sid %s failed.\n",
468 sid_string_dbg(ids[i]->sid)));
469 continue;
472 switch(lsa_type) {
473 case SID_NAME_USER:
474 id->xid.type = map->type = ID_TYPE_UID;
475 if (ctx->user_cn && ctx->realm != NULL) {
476 name = talloc_asprintf(mem_ctx, "%s@%s",
477 name, ctx->realm);
479 id->xid.type = map->type = ID_TYPE_UID;
480 break;
482 case SID_NAME_DOM_GRP:
483 case SID_NAME_ALIAS:
484 case SID_NAME_WKN_GRP:
485 if (ctx->realm != NULL) {
486 name = talloc_asprintf(mem_ctx, "%s@%s",
487 name, ctx->realm);
489 id->xid.type = map->type = ID_TYPE_GID;
490 break;
492 default:
493 DEBUG(1, ("Unknown lsa type %d for sid %s\n",
494 lsa_type, sid_string_dbg(id->sid)));
495 id->status = ID_UNMAPPED;
496 continue;
499 map->map = id;
500 id->status = ID_UNKNOWN;
501 map->name = strupper_talloc(mem_ctx, name);
503 if (!map->name) {
504 return NT_STATUS_NO_MEMORY;
508 return NT_STATUS_OK;
512 * Find id_map entry by looking up the name in the internal
513 * mapping array.
515 static struct id_map* idmap_rfc2307_find_map(struct idmap_rfc2307_map *maps,
516 enum id_type type,
517 const char *name)
519 int i;
521 DEBUG(10, ("Looking for name %s, type %d\n", name, type));
523 for (i = 0; maps[i].map != NULL; i++) {
524 DEBUG(10, ("Entry %d: name %s, type %d\n",
525 i, maps[i].name, maps[i].type));
526 if (type == maps[i].type && strcmp(name, maps[i].name) == 0) {
527 return maps[i].map;
531 return NULL;
534 static void idmap_rfc2307_map_xid_results(struct idmap_rfc2307_context *ctx,
535 TALLOC_CTX *mem_ctx,
536 struct idmap_rfc2307_map *maps,
537 LDAPMessage *result,
538 struct idmap_domain *dom,
539 const char **attrs, enum id_type type)
541 int count, i;
542 LDAPMessage *entry;
544 count = ldap_count_entries(ctx->ldap, result);
546 for (i = 0; i < count; i++) {
547 uint32_t id;
548 char *name;
549 bool b;
550 struct id_map *id_map;
552 if (i == 0) {
553 entry = ldap_first_entry(ctx->ldap, result);
554 } else {
555 entry = ldap_next_entry(ctx->ldap, entry);
557 if (!entry) {
558 DEBUG(2, ("Unable to fetch entry.\n"));
559 break;
562 name = smbldap_talloc_single_attribute(ctx->ldap, entry,
563 attrs[0], mem_ctx);
564 if (!name) {
565 DEBUG(1, ("Could not get user name\n"));
566 continue;
569 b = idmap_rfc2307_get_uint32(ctx->ldap, entry, attrs[1], &id);
570 if (!b) {
571 DEBUG(5, ("Could not pull id for record %s\n", name));
572 continue;
575 if (!idmap_unix_id_is_in_range(id, dom)) {
576 DEBUG(5, ("Requested id (%u) out of range (%u - %u).\n",
577 id, dom->low_id, dom->high_id));
578 continue;
581 if (!strupper_m(name)) {
582 DEBUG(5, ("Could not convert %s to uppercase\n", name));
583 continue;
585 id_map = idmap_rfc2307_find_map(maps, type, name);
586 if (!id_map) {
587 DEBUG(0, ("Could not find mapping entry for name %s\n",
588 name));
589 continue;
592 id_map->xid.id = id;
593 id_map->status = ID_MAPPED;
598 * Map sids to names and then to unixids.
600 static NTSTATUS idmap_rfc2307_sids_to_unixids(struct idmap_domain *dom,
601 struct id_map **ids)
603 struct idmap_rfc2307_context *ctx;
604 TALLOC_CTX *mem_ctx;
605 struct idmap_rfc2307_map *int_maps;
606 int cnt_usr = 0, cnt_grp = 0, idx = 0;
607 char *fltr_usr = NULL, *fltr_grp = NULL;
608 NTSTATUS ret;
609 int i;
611 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
612 mem_ctx = talloc_new(talloc_tos());
613 if (!mem_ctx) {
614 return NT_STATUS_NO_MEMORY;
617 if (ctx->check_connection) {
618 ret = ctx->check_connection(dom);
619 if (!NT_STATUS_IS_OK(ret)) {
620 goto out;
624 for (i = 0; ids[i]; i++);
625 int_maps = talloc_zero_array(mem_ctx, struct idmap_rfc2307_map, i);
626 if (!int_maps) {
627 ret = NT_STATUS_NO_MEMORY;
628 goto out;
631 ret = idmap_rfc_2307_sids_to_names(mem_ctx, ids, int_maps, ctx);
632 if (!NT_STATUS_IS_OK(ret)) {
633 goto out;
636 again:
637 if (!fltr_usr) {
638 /* prepare new user query, see getpwuid() in RFC2307 */
639 fltr_usr = talloc_asprintf(mem_ctx,
640 "(&(objectClass=posixAccount)(|");
643 if (!fltr_grp) {
644 /* prepare new group query, see getgrgid() in RFC2307 */
645 fltr_grp = talloc_asprintf(mem_ctx,
646 "(&(objectClass=posixGroup)(|");
649 if (!fltr_usr || !fltr_grp) {
650 ret = NT_STATUS_NO_MEMORY;
651 goto out;
654 while (cnt_usr < IDMAP_LDAP_MAX_IDS &&
655 cnt_grp < IDMAP_LDAP_MAX_IDS && ids[idx]) {
656 struct id_map *id = ids[idx];
657 struct idmap_rfc2307_map *map = &int_maps[idx];
659 switch(id->xid.type) {
660 case ID_TYPE_UID:
661 fltr_usr = talloc_asprintf_append_buffer(fltr_usr,
662 "(%s=%s)", (ctx->user_cn ? "cn" : "uid"),
663 map->name);
664 cnt_usr++;
665 break;
667 case ID_TYPE_GID:
668 fltr_grp = talloc_asprintf_append_buffer(fltr_grp,
669 "(cn=%s)", map->name);
670 cnt_grp++;
671 break;
673 default:
674 break;
677 if (!fltr_usr || !fltr_grp) {
678 ret = NT_STATUS_NO_MEMORY;
679 goto out;
682 idx++;
685 if (cnt_usr == IDMAP_LDAP_MAX_IDS || (cnt_usr != 0 && !ids[idx])) {
686 const char *attrs[] = { NULL, /* uid or cn */
687 "uidNumber",
688 NULL };
689 LDAPMessage *result;
691 fltr_usr = talloc_strdup_append(fltr_usr, "))");
692 if (!fltr_usr) {
693 ret = NT_STATUS_NO_MEMORY;
694 goto out;
697 attrs[0] = ctx->user_cn ? "cn" : "uid";
698 ret = ctx->search(ctx, ctx->bind_path_user, fltr_usr, attrs,
699 &result);
700 if (!NT_STATUS_IS_OK(ret)) {
701 goto out;
704 idmap_rfc2307_map_xid_results(ctx, mem_ctx, int_maps,
705 result, dom, attrs, ID_TYPE_UID);
707 cnt_usr = 0;
708 TALLOC_FREE(fltr_usr);
711 if (cnt_grp == IDMAP_LDAP_MAX_IDS || (cnt_grp != 0 && !ids[idx])) {
712 const char *attrs[] = {"cn", "gidNumber", NULL };
713 LDAPMessage *result;
715 fltr_grp = talloc_strdup_append(fltr_grp, "))");
716 if (!fltr_grp) {
717 ret = NT_STATUS_NO_MEMORY;
718 goto out;
721 ret = ctx->search(ctx, ctx->bind_path_group, fltr_grp, attrs,
722 &result);
723 if (!NT_STATUS_IS_OK(ret)) {
724 goto out;
727 idmap_rfc2307_map_xid_results(ctx, mem_ctx, int_maps, result,
728 dom, attrs, ID_TYPE_GID);
729 cnt_grp = 0;
730 TALLOC_FREE(fltr_grp);
733 if (ids[idx]) {
734 goto again;
737 ret = NT_STATUS_OK;
739 out:
740 talloc_free(mem_ctx);
741 return ret;
744 static int idmap_rfc2307_context_destructor(struct idmap_rfc2307_context *ctx)
746 if (ctx->ads != NULL) {
747 /* we own this ADS_STRUCT so make sure it goes away */
748 ctx->ads->is_mine = True;
749 ads_destroy( &ctx->ads );
750 ctx->ads = NULL;
753 if (ctx->smbldap_state != NULL) {
754 smbldap_free_struct(&ctx->smbldap_state);
757 return 0;
760 static NTSTATUS idmap_rfc2307_initialize(struct idmap_domain *domain)
762 struct idmap_rfc2307_context *ctx;
763 const char *bind_path_user, *bind_path_group, *ldap_server, *realm;
764 NTSTATUS status;
766 ctx = talloc_zero(domain, struct idmap_rfc2307_context);
767 if (ctx == NULL) {
768 return NT_STATUS_NO_MEMORY;
770 talloc_set_destructor(ctx, idmap_rfc2307_context_destructor);
772 bind_path_user = idmap_config_const_string(
773 domain->name, "bind_path_user", NULL);
774 if (bind_path_user == NULL) {
775 status = NT_STATUS_INVALID_PARAMETER;
776 goto err;
778 ctx->bind_path_user = talloc_strdup(ctx, bind_path_user);
779 if (ctx->bind_path_user == NULL) {
780 status = NT_STATUS_NO_MEMORY;
781 goto err;
784 bind_path_group = idmap_config_const_string(
785 domain->name, "bind_path_group", NULL);
786 if (bind_path_group == NULL) {
787 status = NT_STATUS_INVALID_PARAMETER;
788 goto err;
790 ctx->bind_path_group = talloc_strdup(ctx, bind_path_group);
791 if (ctx->bind_path_group == NULL) {
792 status = NT_STATUS_NO_MEMORY;
793 goto err;
796 ldap_server = idmap_config_const_string(
797 domain->name, "ldap_server", NULL);
798 if (!ldap_server) {
799 status = NT_STATUS_INVALID_PARAMETER;
800 goto err;
803 if (strcmp(ldap_server, "stand-alone") == 0) {
804 status = idmap_rfc2307_init_ldap(ctx, domain->name);
806 } else if (strcmp(ldap_server, "ad") == 0) {
807 status = idmap_rfc2307_init_ads(ctx, domain->name);
809 } else {
810 status = NT_STATUS_INVALID_PARAMETER;
813 if (!NT_STATUS_IS_OK(status)) {
814 goto err;
817 realm = idmap_config_const_string(domain->name, "realm", NULL);
818 if (realm) {
819 ctx->realm = talloc_strdup(ctx, realm);
820 if (ctx->realm == NULL) {
821 status = NT_STATUS_NO_MEMORY;
822 goto err;
826 ctx->user_cn = idmap_config_bool(domain->name, "user_cn", false);
828 domain->private_data = ctx;
829 return NT_STATUS_OK;
831 err:
832 talloc_free(ctx);
833 return status;
836 static struct idmap_methods rfc2307_methods = {
837 .init = idmap_rfc2307_initialize,
838 .unixids_to_sids = idmap_rfc2307_unixids_to_sids,
839 .sids_to_unixids = idmap_rfc2307_sids_to_unixids,
842 static_decl_idmap;
843 NTSTATUS idmap_rfc2307_init(TALLOC_CTX *ctx)
845 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "rfc2307",
846 &rfc2307_methods);