s3: libsmb: Make a comment note that cli_set_ea() needs some internal changes before...
[Samba.git] / source3 / winbindd / idmap_rfc2307.c
blob34cc5cd179f7184a786435698524f4a4bdb3c623
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 "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 *cfg_opt)
114 const char *ldap_domain;
116 ctx->search = idmap_rfc2307_ads_search;
117 ctx->check_connection = idmap_rfc2307_ads_check_connection;
119 ldap_domain = lp_parm_const_string(-1, cfg_opt, "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 = ctx->smbldap_state->ldap_struct;
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 struct idmap_domain *dom,
171 const char *config_option)
173 NTSTATUS ret;
174 char *url;
175 char *secret = NULL;
176 const char *ldap_url, *user_dn;
177 TALLOC_CTX *mem_ctx = ctx;
179 ldap_url = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
180 if (!ldap_url) {
181 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
182 return NT_STATUS_UNSUCCESSFUL;
185 url = talloc_strdup(talloc_tos(), ldap_url);
187 user_dn = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
188 if (user_dn) {
189 secret = idmap_fetch_secret("ldap", dom->name, user_dn);
190 if (!secret) {
191 ret = NT_STATUS_ACCESS_DENIED;
192 goto done;
196 /* assume anonymous if we don't have a specified user */
197 ret = smbldap_init(mem_ctx, winbind_event_context(), url,
198 (user_dn == NULL), user_dn, secret,
199 &ctx->smbldap_state);
200 SAFE_FREE(secret);
201 if (!NT_STATUS_IS_OK(ret)) {
202 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", url));
203 goto done;
206 ctx->search = idmap_rfc2307_ldap_search;
208 done:
209 talloc_free(url);
210 return ret;
214 * common code for stand-alone LDAP and ADS
217 static void idmap_rfc2307_map_sid_results(struct idmap_rfc2307_context *ctx,
218 TALLOC_CTX *mem_ctx,
219 struct id_map **ids,
220 LDAPMessage *result,
221 const char *dom_name,
222 const char **attrs, int type)
224 int count, i;
225 LDAPMessage *entry;
227 count = ldap_count_entries(ctx->ldap, result);
229 for (i = 0; i < count; i++) {
230 char *name;
231 enum lsa_SidType lsa_type;
232 struct id_map *map;
233 uint32_t id;
234 bool b;
236 if (i == 0) {
237 entry = ldap_first_entry(ctx->ldap, result);
238 } else {
239 entry = ldap_next_entry(ctx->ldap, result);
241 if (!entry) {
242 DEBUG(2, ("Unable to fetch entry.\n"));
243 break;
246 name = smbldap_talloc_single_attribute(ctx->ldap, entry,
247 attrs[0], mem_ctx);
248 if (!name) {
249 DEBUG(1, ("Could not get user name\n"));
250 continue;
253 b = idmap_rfc2307_get_uint32(ctx->ldap, entry, attrs[1], &id);
254 if (!b) {
255 DEBUG(1, ("Could not pull id for record %s\n", name));
256 continue;
259 map = idmap_find_map_by_id(ids, type, id);
260 if (!map) {
261 DEBUG(1, ("Could not find id %d, name %s\n", id, name));
262 continue;
265 if (ctx->realm != NULL) {
266 /* Strip @realm from user or group name */
267 char *delim;
269 delim = strchr(name, '@');
270 if (delim) {
271 *delim = '\0';
275 /* by default calls to winbindd are disabled
276 the following call will not recurse so this is safe */
277 (void)winbind_on();
278 /* Lookup name from PDC using lsa_lookup_names() */
279 b = winbind_lookup_name(dom_name, name, map->sid, &lsa_type);
280 (void)winbind_off();
282 if (!b) {
283 DEBUG(1, ("SID lookup failed for id %d, %s\n",
284 id, name));
285 continue;
288 if (type == ID_TYPE_UID && lsa_type != SID_NAME_USER) {
289 DEBUG(1, ("Wrong type %d for user name %s\n",
290 type, name));
291 continue;
294 if (type == ID_TYPE_GID && lsa_type != SID_NAME_DOM_GRP &&
295 lsa_type != SID_NAME_ALIAS &&
296 lsa_type != SID_NAME_WKN_GRP) {
297 DEBUG(1, ("Wrong type %d for group name %s\n",
298 type, name));
299 continue;
302 map->status = ID_MAPPED;
307 * Map unixids to names and then to sids.
309 static NTSTATUS idmap_rfc2307_unixids_to_sids(struct idmap_domain *dom,
310 struct id_map **ids)
312 struct idmap_rfc2307_context *ctx;
313 char *fltr_usr = NULL, *fltr_grp = NULL;
314 TALLOC_CTX *mem_ctx;
315 int cnt_usr = 0, cnt_grp = 0, idx = 0, bidx = 0;
316 LDAPMessage *result = NULL;
317 NTSTATUS ret;
319 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
320 mem_ctx = talloc_new(ctx);
321 if (!mem_ctx) {
322 return NT_STATUS_NO_MEMORY;
325 if (ctx->check_connection) {
326 ret = ctx->check_connection(dom);
327 if (!NT_STATUS_IS_OK(ret)) {
328 goto out;
332 again:
333 bidx = idx;
335 if (!fltr_usr) {
336 /* prepare new user query, see getpwuid() in RFC2307 */
337 fltr_usr = talloc_asprintf(mem_ctx,
338 "(&(objectClass=posixAccount)(|");
341 if (!fltr_grp) {
342 /* prepare new group query, see getgrgid() in RFC2307 */
343 fltr_grp = talloc_asprintf(mem_ctx,
344 "(&(objectClass=posixGroup)(|");
347 if (!fltr_usr || !fltr_grp) {
348 ret = NT_STATUS_NO_MEMORY;
349 goto out;
352 while (cnt_usr < IDMAP_LDAP_MAX_IDS &&
353 cnt_grp < IDMAP_LDAP_MAX_IDS && ids[idx]) {
355 switch (ids[idx]->xid.type) {
356 case ID_TYPE_UID:
357 fltr_usr = talloc_asprintf_append_buffer(fltr_usr,
358 "(uidNumber=%d)", ids[idx]->xid.id);
359 cnt_usr++;
360 break;
361 case ID_TYPE_GID:
362 fltr_grp = talloc_asprintf_append_buffer(fltr_grp,
363 "(gidNumber=%d)", ids[idx]->xid.id);
364 cnt_grp++;
365 break;
366 default:
367 DEBUG(3, ("Error: unknown ID type %d\n",
368 ids[idx]->xid.type));
369 ret = NT_STATUS_UNSUCCESSFUL;
370 goto out;
373 if (!fltr_usr || !fltr_grp) {
374 ret = NT_STATUS_NO_MEMORY;
375 goto out;
378 idx++;
381 if (cnt_usr == IDMAP_LDAP_MAX_IDS || (cnt_usr != 0 && !ids[idx])) {
382 const char *attrs[] = { NULL, /* uid or cn */
383 "uidNumber",
384 NULL };
386 fltr_usr = talloc_strdup_append(fltr_usr, "))");
387 if (!fltr_usr) {
388 ret = NT_STATUS_NO_MEMORY;
389 goto out;
392 attrs[0] = ctx->user_cn ? "cn" : "uid";
393 ret = ctx->search(ctx, ctx->bind_path_user, fltr_usr, attrs,
394 &result);
395 if (!NT_STATUS_IS_OK(ret)) {
396 goto out;
399 idmap_rfc2307_map_sid_results(ctx, mem_ctx, &ids[bidx], result,
400 dom->name, attrs, ID_TYPE_UID);
401 cnt_usr = 0;
402 TALLOC_FREE(fltr_usr);
405 if (cnt_grp == IDMAP_LDAP_MAX_IDS || (cnt_grp != 0 && !ids[idx])) {
406 const char *attrs[] = { "cn", "gidNumber", NULL };
408 fltr_grp = talloc_strdup_append(fltr_grp, "))");
409 if (!fltr_grp) {
410 ret = NT_STATUS_NO_MEMORY;
411 goto out;
413 ret = ctx->search(ctx, ctx->bind_path_group, fltr_grp, attrs,
414 &result);
415 if (!NT_STATUS_IS_OK(ret)) {
416 goto out;
419 idmap_rfc2307_map_sid_results(ctx, mem_ctx, &ids[bidx], result,
420 dom->name, attrs, ID_TYPE_GID);
421 cnt_grp = 0;
422 TALLOC_FREE(fltr_grp);
425 if (ids[idx]) {
426 goto again;
429 ret = NT_STATUS_OK;
431 out:
432 talloc_free(mem_ctx);
433 return ret;
436 struct idmap_rfc2307_map {
437 struct id_map *map;
438 const char *name;
439 enum id_type type;
443 * Lookup names for SIDS and store the data in the local mapping
444 * array.
446 static NTSTATUS idmap_rfc_2307_sids_to_names(TALLOC_CTX *mem_ctx,
447 struct id_map **ids,
448 struct idmap_rfc2307_map *maps,
449 struct idmap_rfc2307_context *ctx)
451 int i;
453 for (i = 0; ids[i]; i++) {
454 const char *domain, *name;
455 enum lsa_SidType lsa_type;
456 struct id_map *id = ids[i];
457 struct idmap_rfc2307_map *map = &maps[i];
458 bool b;
460 /* by default calls to winbindd are disabled
461 the following call will not recurse so this is safe */
462 (void)winbind_on();
463 b = winbind_lookup_sid(mem_ctx, ids[i]->sid, &domain, &name,
464 &lsa_type);
465 (void)winbind_off();
467 if (!b) {
468 DEBUG(1, ("Lookup sid %s failed.\n",
469 sid_string_dbg(ids[i]->sid)));
470 continue;
473 switch(lsa_type) {
474 case SID_NAME_USER:
475 id->xid.type = map->type = ID_TYPE_UID;
476 if (ctx->user_cn && ctx->realm != NULL) {
477 name = talloc_asprintf(mem_ctx, "%s@%s",
478 name, ctx->realm);
480 id->xid.type = map->type = ID_TYPE_UID;
481 break;
483 case SID_NAME_DOM_GRP:
484 case SID_NAME_ALIAS:
485 case SID_NAME_WKN_GRP:
486 if (ctx->realm != NULL) {
487 name = talloc_asprintf(mem_ctx, "%s@%s",
488 name, ctx->realm);
490 id->xid.type = map->type = ID_TYPE_GID;
491 break;
493 default:
494 DEBUG(1, ("Unknown lsa type %d for sid %s\n",
495 lsa_type, sid_string_dbg(id->sid)));
496 id->status = ID_UNMAPPED;
497 continue;
500 map->map = id;
501 id->status = ID_UNKNOWN;
502 map->name = strupper_talloc(mem_ctx, name);
504 if (!map->name) {
505 return NT_STATUS_NO_MEMORY;
509 return NT_STATUS_OK;
513 * Find id_map entry by looking up the name in the internal
514 * mapping array.
516 static struct id_map* idmap_rfc2307_find_map(struct idmap_rfc2307_map *maps,
517 enum id_type type,
518 const char *name)
520 int i;
522 DEBUG(10, ("Looking for name %s, type %d\n", name, type));
524 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
525 if (maps[i].map == NULL) { /* end of the run */
526 return NULL;
528 DEBUG(10, ("Entry %d: name %s, type %d\n",
529 i, maps[i].name, maps[i].type));
530 if (type == maps[i].type && strcmp(name, maps[i].name) == 0) {
531 return maps[i].map;
535 return NULL;
538 static void idmap_rfc2307_map_xid_results(struct idmap_rfc2307_context *ctx,
539 TALLOC_CTX *mem_ctx,
540 struct idmap_rfc2307_map *maps,
541 LDAPMessage *result,
542 struct idmap_domain *dom,
543 const char **attrs, enum id_type type)
545 int count, i;
546 LDAPMessage *entry;
548 count = ldap_count_entries(ctx->ldap, result);
550 for (i = 0; i < count; i++) {
551 uint32_t id;
552 char *name;
553 bool b;
554 struct id_map *id_map;
556 if (i == 0) {
557 entry = ldap_first_entry(ctx->ldap, result);
558 } else {
559 entry = ldap_next_entry(ctx->ldap, result);
561 if (!entry) {
562 DEBUG(2, ("Unable to fetch entry.\n"));
563 break;
566 name = smbldap_talloc_single_attribute(ctx->ldap, entry,
567 attrs[0], mem_ctx);
568 if (!name) {
569 DEBUG(1, ("Could not get user name\n"));
570 continue;
573 b = idmap_rfc2307_get_uint32(ctx->ldap, entry, attrs[1], &id);
574 if (!b) {
575 DEBUG(5, ("Could not pull id for record %s\n", name));
576 continue;
579 if (!idmap_unix_id_is_in_range(id, dom)) {
580 DEBUG(5, ("Requested id (%u) out of range (%u - %u).\n",
581 id, dom->low_id, dom->high_id));
582 continue;
585 if (!strupper_m(name)) {
586 DEBUG(5, ("Could not convert %s to uppercase\n", name));
587 continue;
589 id_map = idmap_rfc2307_find_map(maps, type, name);
590 if (!id_map) {
591 DEBUG(0, ("Could not find mapping entry for name %s\n",
592 name));
593 continue;
596 id_map->xid.id = id;
597 id_map->status = ID_MAPPED;
602 * Map sids to names and then to unixids.
604 static NTSTATUS idmap_rfc2307_sids_to_unixids(struct idmap_domain *dom,
605 struct id_map **ids)
607 struct idmap_rfc2307_context *ctx;
608 TALLOC_CTX *mem_ctx;
609 struct idmap_rfc2307_map *int_maps;
610 int cnt_usr = 0, cnt_grp = 0, idx = 0;
611 char *fltr_usr = NULL, *fltr_grp = NULL;
612 NTSTATUS ret;
613 int i;
615 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
616 mem_ctx = talloc_new(talloc_tos());
617 if (!mem_ctx) {
618 return NT_STATUS_NO_MEMORY;
621 if (ctx->check_connection) {
622 ret = ctx->check_connection(dom);
623 if (!NT_STATUS_IS_OK(ret)) {
624 goto out;
628 for (i = 0; ids[i]; i++);
629 int_maps = talloc_zero_array(mem_ctx, struct idmap_rfc2307_map, i);
630 if (!int_maps) {
631 ret = NT_STATUS_NO_MEMORY;
632 goto out;
635 ret = idmap_rfc_2307_sids_to_names(mem_ctx, ids, int_maps, ctx);
636 if (!NT_STATUS_IS_OK(ret)) {
637 goto out;
640 again:
641 if (!fltr_usr) {
642 /* prepare new user query, see getpwuid() in RFC2307 */
643 fltr_usr = talloc_asprintf(mem_ctx,
644 "(&(objectClass=posixAccount)(|");
647 if (!fltr_grp) {
648 /* prepare new group query, see getgrgid() in RFC2307 */
649 fltr_grp = talloc_asprintf(mem_ctx,
650 "(&(objectClass=posixGroup)(|");
653 if (!fltr_usr || !fltr_grp) {
654 ret = NT_STATUS_NO_MEMORY;
655 goto out;
658 while (cnt_usr < IDMAP_LDAP_MAX_IDS &&
659 cnt_grp < IDMAP_LDAP_MAX_IDS && ids[idx]) {
660 struct id_map *id = ids[idx];
661 struct idmap_rfc2307_map *map = &int_maps[idx];
663 switch(id->xid.type) {
664 case ID_TYPE_UID:
665 fltr_usr = talloc_asprintf_append_buffer(fltr_usr,
666 "(%s=%s)", (ctx->user_cn ? "cn" : "uid"),
667 map->name);
668 cnt_usr++;
669 break;
671 case ID_TYPE_GID:
672 fltr_grp = talloc_asprintf_append_buffer(fltr_grp,
673 "(cn=%s)", map->name);
674 cnt_grp++;
675 break;
677 default:
678 break;
681 if (!fltr_usr || !fltr_grp) {
682 ret = NT_STATUS_NO_MEMORY;
683 goto out;
686 idx++;
689 if (cnt_usr == IDMAP_LDAP_MAX_IDS || (cnt_usr != 0 && !ids[idx])) {
690 const char *attrs[] = { NULL, /* uid or cn */
691 "uidNumber",
692 NULL };
693 LDAPMessage *result;
695 fltr_usr = talloc_strdup_append(fltr_usr, "))");
696 if (!fltr_usr) {
697 ret = NT_STATUS_NO_MEMORY;
698 goto out;
701 attrs[0] = ctx->user_cn ? "cn" : "uid";
702 ret = ctx->search(ctx, ctx->bind_path_user, fltr_usr, attrs,
703 &result);
704 if (!NT_STATUS_IS_OK(ret)) {
705 goto out;
708 idmap_rfc2307_map_xid_results(ctx, mem_ctx, int_maps,
709 result, dom, attrs, ID_TYPE_UID);
711 cnt_usr = 0;
712 TALLOC_FREE(fltr_usr);
715 if (cnt_grp == IDMAP_LDAP_MAX_IDS || (cnt_grp != 0 && !ids[idx])) {
716 const char *attrs[] = {"cn", "gidNumber", NULL };
717 LDAPMessage *result;
719 fltr_grp = talloc_strdup_append(fltr_grp, "))");
720 if (!fltr_grp) {
721 ret = NT_STATUS_NO_MEMORY;
722 goto out;
725 ret = ctx->search(ctx, ctx->bind_path_group, fltr_grp, attrs,
726 &result);
727 if (!NT_STATUS_IS_OK(ret)) {
728 goto out;
731 idmap_rfc2307_map_xid_results(ctx, mem_ctx, int_maps, result,
732 dom, attrs, ID_TYPE_GID);
733 cnt_grp = 0;
734 TALLOC_FREE(fltr_grp);
737 if (ids[idx]) {
738 goto again;
741 ret = NT_STATUS_OK;
743 out:
744 talloc_free(mem_ctx);
745 return ret;
748 static int idmap_rfc2307_context_destructor(struct idmap_rfc2307_context *ctx)
750 if (ctx->ads != NULL) {
751 /* we own this ADS_STRUCT so make sure it goes away */
752 ctx->ads->is_mine = True;
753 ads_destroy( &ctx->ads );
754 ctx->ads = NULL;
757 if (ctx->smbldap_state != NULL) {
758 smbldap_free_struct(&ctx->smbldap_state);
761 return 0;
764 static NTSTATUS idmap_rfc2307_initialize(struct idmap_domain *domain)
766 struct idmap_rfc2307_context *ctx;
767 char *cfg_opt;
768 const char *bind_path_user, *bind_path_group, *ldap_server, *realm;
769 NTSTATUS status;
771 ctx = talloc_zero(domain, struct idmap_rfc2307_context);
772 if (ctx == NULL) {
773 return NT_STATUS_NO_MEMORY;
775 talloc_set_destructor(ctx, idmap_rfc2307_context_destructor);
777 cfg_opt = talloc_asprintf(ctx, "idmap config %s", domain->name);
778 if (cfg_opt == NULL) {
779 status = NT_STATUS_NO_MEMORY;
780 goto err;
783 bind_path_user = lp_parm_const_string(-1, cfg_opt, "bind_path_user",
784 NULL);
785 if (bind_path_user) {
786 ctx->bind_path_user = talloc_strdup(ctx, bind_path_user);
787 if (ctx->bind_path_user == NULL) {
788 status = NT_STATUS_NO_MEMORY;
789 goto err;
791 } else {
792 status = NT_STATUS_INVALID_PARAMETER;
793 goto err;
796 bind_path_group = lp_parm_const_string(-1, cfg_opt, "bind_path_group",
797 NULL);
798 if (bind_path_group) {
799 ctx->bind_path_group = talloc_strdup(ctx, bind_path_group);
800 if (ctx->bind_path_group == NULL) {
801 status = NT_STATUS_NO_MEMORY;
802 goto err;
804 } else {
805 status = NT_STATUS_INVALID_PARAMETER;
806 goto err;
809 ldap_server = lp_parm_const_string(-1, cfg_opt, "ldap_server", NULL);
810 if (!ldap_server) {
811 status = NT_STATUS_INVALID_PARAMETER;
812 goto err;
815 if (strcmp(ldap_server, "stand-alone") == 0) {
816 status = idmap_rfc2307_init_ldap(ctx, domain, cfg_opt);
818 } else if (strcmp(ldap_server, "ad") == 0) {
819 status = idmap_rfc2307_init_ads(ctx, cfg_opt);
821 } else {
822 status = NT_STATUS_INVALID_PARAMETER;
825 if (!NT_STATUS_IS_OK(status)) {
826 goto err;
829 realm = lp_parm_const_string(-1, cfg_opt, "realm", NULL);
830 if (realm) {
831 ctx->realm = talloc_strdup(ctx, realm);
832 if (ctx->realm == NULL) {
833 status = NT_STATUS_NO_MEMORY;
834 goto err;
838 ctx->user_cn = lp_parm_bool(-1, cfg_opt, "user_cn", false);
840 domain->private_data = ctx;
841 talloc_free(cfg_opt);
842 return NT_STATUS_OK;
844 err:
845 talloc_free(cfg_opt);
846 talloc_free(ctx);
847 return status;
850 static struct idmap_methods rfc2307_methods = {
851 .init = idmap_rfc2307_initialize,
852 .unixids_to_sids = idmap_rfc2307_unixids_to_sids,
853 .sids_to_unixids = idmap_rfc2307_sids_to_unixids,
856 static_decl_idmap;
857 NTSTATUS idmap_rfc2307_init(void)
859 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "rfc2307",
860 &rfc2307_methods);