idmap_rfc2307: Fix wbinfo --gid-to-sid query
[Samba.git] / source3 / winbindd / idmap_rfc2307.c
blobf2fcd984868deb92e5d759557eceee9a03d402e8
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 cn_realm;
42 bool user_cn;
43 const char *realm;
46 * Pointer to ldap struct in ads or smbldap_state, has to be
47 * updated after connecting to server
49 LDAP *ldap;
51 /* Optional function to check connection to server */
52 NTSTATUS (*check_connection)(struct idmap_domain *dom);
54 /* Issue ldap query */
55 NTSTATUS (*search)(struct idmap_rfc2307_context *ctx,
56 const char *bind_path, const char *expr,
57 const char **attrs, LDAPMessage **res);
59 /* Access to LDAP in AD server */
60 ADS_STRUCT *ads;
62 /* Access to stand-alone LDAP server */
63 struct smbldap_state *smbldap_state;
67 * backend functions for LDAP queries through ADS
70 static NTSTATUS idmap_rfc2307_ads_check_connection(struct idmap_domain *dom)
72 struct idmap_rfc2307_context *ctx;
73 const char *dom_name = dom->name;
74 ADS_STATUS status;
76 DEBUG(10, ("ad_idmap_cached_connection: called for domain '%s'\n",
77 dom->name));
79 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
80 dom_name = ctx->ldap_domain ? ctx->ldap_domain : dom->name;
82 status = ads_idmap_cached_connection(&ctx->ads, dom_name);
83 if (ADS_ERR_OK(status)) {
84 ctx->ldap = ctx->ads->ldap.ld;
85 if (ctx->cn_realm) {
86 ctx->realm = ctx->ads->server.realm;
88 } else {
89 DEBUG(1, ("Could not connect to domain %s: %s\n", dom->name,
90 ads_errstr(status)));
93 return ads_ntstatus(status);
96 static NTSTATUS idmap_rfc2307_ads_search(struct idmap_rfc2307_context *ctx,
97 const char *bind_path,
98 const char *expr,
99 const char **attrs,
100 LDAPMessage **result)
102 ADS_STATUS status;
104 status = ads_do_search_retry(ctx->ads, bind_path,
105 LDAP_SCOPE_SUBTREE, expr, attrs, result);
106 ctx->ldap = ctx->ads->ldap.ld;
107 return ads_ntstatus(status);
110 static NTSTATUS idmap_rfc2307_init_ads(struct idmap_rfc2307_context *ctx,
111 const char *cfg_opt)
113 const char *ldap_domain;
115 ctx->search = idmap_rfc2307_ads_search;
116 ctx->check_connection = idmap_rfc2307_ads_check_connection;
118 ldap_domain = lp_parm_const_string(-1, cfg_opt, "ldap_domain",
119 NULL);
120 if (ldap_domain) {
121 ctx->ldap_domain = talloc_strdup(ctx, ldap_domain);
122 if (ctx->ldap_domain == NULL) {
123 return NT_STATUS_NO_MEMORY;
127 return NT_STATUS_OK;
131 * backend function for LDAP queries through stand-alone LDAP server
134 static NTSTATUS idmap_rfc2307_ldap_search(struct idmap_rfc2307_context *ctx,
135 const char *bind_path,
136 const char *expr,
137 const char **attrs,
138 LDAPMessage **result)
140 int ret;
142 ret = smbldap_search(ctx->smbldap_state, bind_path, LDAP_SCOPE_SUBTREE,
143 expr, attrs, 0, result);
144 ctx->ldap = ctx->smbldap_state->ldap_struct;
146 if (ret == LDAP_SUCCESS) {
147 return NT_STATUS_OK;
150 return NT_STATUS_LDAP(ret);
153 static bool idmap_rfc2307_get_uint32(LDAP *ldap, LDAPMessage *entry,
154 const char *field, uint32 *value)
156 bool b;
157 char str[20];
159 b = smbldap_get_single_attribute(ldap, entry, field, str, sizeof(str));
161 if (b) {
162 *value = atoi(str);
165 return b;
168 static NTSTATUS idmap_rfc2307_init_ldap(struct idmap_rfc2307_context *ctx,
169 struct idmap_domain *dom,
170 const char *config_option)
172 NTSTATUS ret;
173 char *url;
174 char *secret = NULL;
175 const char *ldap_url, *user_dn, *ldap_realm;
176 TALLOC_CTX *mem_ctx = ctx;
178 ldap_url = lp_parm_const_string(-1, config_option, "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 = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
187 if (user_dn) {
188 secret = idmap_fetch_secret("ldap", dom->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, winbind_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 if (ctx->cn_realm) {
208 ldap_realm = lp_parm_const_string(-1, config_option,
209 "ldap_realm", NULL);
210 if (!ldap_realm) {
211 DEBUG(1, ("ERROR: cn_realm set, "
212 "but ldap_realm is missing\n"));
213 ret = NT_STATUS_UNSUCCESSFUL;
214 goto done;
216 ctx->realm = talloc_strdup(mem_ctx, ldap_realm);
217 if (!ctx->realm) {
218 ret = NT_STATUS_NO_MEMORY;
222 done:
223 talloc_free(url);
224 return ret;
228 * common code for stand-alone LDAP and ADS
231 static void idmap_rfc2307_map_sid_results(struct idmap_rfc2307_context *ctx,
232 TALLOC_CTX *mem_ctx,
233 struct id_map **ids,
234 LDAPMessage *result,
235 const char *dom_name,
236 const char **attrs, int type)
238 int count, i;
239 LDAPMessage *entry;
241 count = ldap_count_entries(ctx->ldap, result);
243 for (i = 0; i < count; i++) {
244 char *name;
245 enum lsa_SidType lsa_type;
246 struct id_map *map;
247 uint32_t id;
248 bool b;
250 if (i == 0) {
251 entry = ldap_first_entry(ctx->ldap, result);
252 } else {
253 entry = ldap_next_entry(ctx->ldap, result);
255 if (!entry) {
256 DEBUG(2, ("Unable to fetch entry.\n"));
257 break;
260 name = smbldap_talloc_single_attribute(ctx->ldap, entry,
261 attrs[0], mem_ctx);
262 if (!name) {
263 DEBUG(1, ("Could not get user name\n"));
264 continue;
267 b = idmap_rfc2307_get_uint32(ctx->ldap, entry, attrs[1], &id);
268 if (!b) {
269 DEBUG(1, ("Could not pull id for record %s\n", name));
270 continue;
273 map = idmap_find_map_by_id(ids, type, id);
274 if (!map) {
275 DEBUG(1, ("Could not find id %d, name %s\n", id, name));
276 continue;
279 if (ctx->cn_realm) {
280 /* Strip @realm from user or group name */
281 char *delim;
283 delim = strchr(name, '@');
284 if (delim) {
285 *delim = '\0';
289 /* by default calls to winbindd are disabled
290 the following call will not recurse so this is safe */
291 (void)winbind_on();
292 /* Lookup name from PDC using lsa_lookup_names() */
293 b = winbind_lookup_name(dom_name, name, map->sid, &lsa_type);
294 (void)winbind_off();
296 if (!b) {
297 DEBUG(1, ("SID lookup failed for id %d, %s\n",
298 id, name));
299 continue;
302 if (type == ID_TYPE_UID && lsa_type != SID_NAME_USER) {
303 DEBUG(1, ("Wrong type %d for user name %s\n",
304 type, name));
305 continue;
308 if (type == ID_TYPE_GID && lsa_type != SID_NAME_DOM_GRP &&
309 lsa_type != SID_NAME_ALIAS &&
310 lsa_type != SID_NAME_WKN_GRP) {
311 DEBUG(1, ("Wrong type %d for group name %s\n",
312 type, name));
313 continue;
316 map->status = ID_MAPPED;
321 * Map unixids to names and then to sids.
323 static NTSTATUS idmap_rfc2307_unixids_to_sids(struct idmap_domain *dom,
324 struct id_map **ids)
326 struct idmap_rfc2307_context *ctx;
327 char *fltr_usr = NULL, *fltr_grp = NULL;
328 TALLOC_CTX *mem_ctx;
329 int cnt_usr = 0, cnt_grp = 0, idx = 0, bidx = 0;
330 LDAPMessage *result = NULL;
331 NTSTATUS ret;
333 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
334 mem_ctx = talloc_new(ctx);
335 if (!mem_ctx) {
336 return NT_STATUS_NO_MEMORY;
339 if (ctx->check_connection) {
340 ret = ctx->check_connection(dom);
341 if (!NT_STATUS_IS_OK(ret)) {
342 goto out;
346 again:
347 bidx = idx;
349 if (!fltr_usr) {
350 /* prepare new user query, see getpwuid() in RFC2307 */
351 fltr_usr = talloc_asprintf(mem_ctx,
352 "(&(objectClass=posixAccount)(|");
355 if (!fltr_grp) {
356 /* prepare new group query, see getgrgid() in RFC2307 */
357 fltr_grp = talloc_asprintf(mem_ctx,
358 "(&(objectClass=posixGroup)(|");
361 if (!fltr_usr || !fltr_grp) {
362 ret = NT_STATUS_NO_MEMORY;
363 goto out;
366 while (cnt_usr < IDMAP_LDAP_MAX_IDS &&
367 cnt_grp < IDMAP_LDAP_MAX_IDS && ids[idx]) {
369 switch (ids[idx]->xid.type) {
370 case ID_TYPE_UID:
371 fltr_usr = talloc_asprintf_append_buffer(fltr_usr,
372 "(uidNumber=%d)", ids[idx]->xid.id);
373 cnt_usr++;
374 break;
375 case ID_TYPE_GID:
376 fltr_grp = talloc_asprintf_append_buffer(fltr_grp,
377 "(gidNumber=%d)", ids[idx]->xid.id);
378 cnt_grp++;
379 break;
380 default:
381 DEBUG(3, ("Error: unknown ID type %d\n",
382 ids[idx]->xid.type));
383 ret = NT_STATUS_UNSUCCESSFUL;
384 goto out;
387 if (!fltr_usr || !fltr_grp) {
388 ret = NT_STATUS_NO_MEMORY;
389 goto out;
392 idx++;
395 if (cnt_usr == IDMAP_LDAP_MAX_IDS || (cnt_usr != 0 && !ids[idx])) {
396 const char *attrs[] = { NULL, /* uid or cn */
397 "uidNumber",
398 NULL };
400 fltr_usr = talloc_strdup_append(fltr_usr, "))");
401 if (!fltr_usr) {
402 ret = NT_STATUS_NO_MEMORY;
403 goto out;
406 attrs[0] = ctx->user_cn ? "cn" : "uid";
407 ret = ctx->search(ctx, ctx->bind_path_user, fltr_usr, attrs,
408 &result);
409 if (!NT_STATUS_IS_OK(ret)) {
410 goto out;
413 idmap_rfc2307_map_sid_results(ctx, mem_ctx, &ids[bidx], result,
414 dom->name, attrs, ID_TYPE_UID);
415 cnt_usr = 0;
416 TALLOC_FREE(fltr_usr);
419 if (cnt_grp == IDMAP_LDAP_MAX_IDS || (cnt_grp != 0 && !ids[idx])) {
420 const char *attrs[] = { "cn", "gidNumber", NULL };
422 fltr_grp = talloc_strdup_append(fltr_grp, "))");
423 if (!fltr_grp) {
424 ret = NT_STATUS_NO_MEMORY;
425 goto out;
427 ret = ctx->search(ctx, ctx->bind_path_group, fltr_grp, attrs,
428 &result);
429 if (!NT_STATUS_IS_OK(ret)) {
430 goto out;
433 idmap_rfc2307_map_sid_results(ctx, mem_ctx, &ids[bidx], result,
434 dom->name, attrs, ID_TYPE_GID);
435 cnt_grp = 0;
436 TALLOC_FREE(fltr_grp);
439 if (ids[idx]) {
440 goto again;
443 ret = NT_STATUS_OK;
445 out:
446 talloc_free(mem_ctx);
447 return ret;
450 struct idmap_rfc2307_map {
451 struct id_map *map;
452 const char *name;
453 enum id_type type;
457 * Lookup names for SIDS and store the data in the local mapping
458 * array.
460 static NTSTATUS idmap_rfc_2307_sids_to_names(TALLOC_CTX *mem_ctx,
461 struct id_map **ids,
462 struct idmap_rfc2307_map *maps,
463 struct idmap_rfc2307_context *ctx)
465 int i;
467 for (i = 0; ids[i]; i++) {
468 const char *domain, *name;
469 enum lsa_SidType lsa_type;
470 struct id_map *id = ids[i];
471 struct idmap_rfc2307_map *map = &maps[i];
472 bool b;
474 /* by default calls to winbindd are disabled
475 the following call will not recurse so this is safe */
476 (void)winbind_on();
477 b = winbind_lookup_sid(mem_ctx, ids[i]->sid, &domain, &name,
478 &lsa_type);
479 (void)winbind_off();
481 if (!b) {
482 DEBUG(1, ("Lookup sid %s failed.\n",
483 sid_string_dbg(ids[i]->sid)));
484 continue;
487 switch(lsa_type) {
488 case SID_NAME_USER:
489 id->xid.type = map->type = ID_TYPE_UID;
490 if (ctx->user_cn && ctx->cn_realm) {
491 name = talloc_asprintf(mem_ctx, "%s@%s",
492 name, ctx->realm);
494 id->xid.type = map->type = ID_TYPE_UID;
495 break;
497 case SID_NAME_DOM_GRP:
498 case SID_NAME_ALIAS:
499 case SID_NAME_WKN_GRP:
500 if (ctx->cn_realm) {
501 name = talloc_asprintf(mem_ctx, "%s@%s",
502 name, ctx->realm);
504 id->xid.type = map->type = ID_TYPE_GID;
505 break;
507 default:
508 DEBUG(1, ("Unknown lsa type %d for sid %s\n",
509 lsa_type, sid_string_dbg(id->sid)));
510 id->status = ID_UNMAPPED;
511 continue;
514 map->map = id;
515 id->status = ID_UNKNOWN;
516 map->name = strupper_talloc(mem_ctx, name);
518 if (!map->name) {
519 return NT_STATUS_NO_MEMORY;
523 return NT_STATUS_OK;
527 * Find id_map entry by looking up the name in the internal
528 * mapping array.
530 static struct id_map* idmap_rfc2307_find_map(struct idmap_rfc2307_map *maps,
531 enum id_type type,
532 const char *name)
534 int i;
536 DEBUG(10, ("Looking for name %s, type %d\n", name, type));
538 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
539 if (maps[i].map == NULL) { /* end of the run */
540 return NULL;
542 DEBUG(10, ("Entry %d: name %s, type %d\n",
543 i, maps[i].name, maps[i].type));
544 if (type == maps[i].type && strcmp(name, maps[i].name) == 0) {
545 return maps[i].map;
549 return NULL;
552 static void idmap_rfc2307_map_xid_results(struct idmap_rfc2307_context *ctx,
553 TALLOC_CTX *mem_ctx,
554 struct id_map **ids,
555 struct idmap_rfc2307_map *maps,
556 LDAPMessage *result,
557 struct idmap_domain *dom,
558 const char **attrs, enum id_type type)
560 int count, i;
561 LDAPMessage *entry;
563 count = ldap_count_entries(ctx->ldap, result);
565 for (i = 0; i < count; i++) {
566 uint32_t id;
567 char *name;
568 bool b;
569 struct id_map *id_map;
571 if (i == 0) {
572 entry = ldap_first_entry(ctx->ldap, result);
573 } else {
574 entry = ldap_next_entry(ctx->ldap, result);
576 if (!entry) {
577 DEBUG(2, ("Unable to fetch entry.\n"));
578 break;
581 name = smbldap_talloc_single_attribute(ctx->ldap, entry,
582 attrs[0], mem_ctx);
583 if (!name) {
584 DEBUG(1, ("Could not get user name\n"));
585 continue;
588 b = idmap_rfc2307_get_uint32(ctx->ldap, entry, attrs[1], &id);
589 if (!b) {
590 DEBUG(5, ("Could not pull id for record %s\n", name));
591 continue;
594 if (!idmap_unix_id_is_in_range(id, dom)) {
595 DEBUG(5, ("Requested id (%u) out of range (%u - %u).\n",
596 id, dom->low_id, dom->high_id));
597 continue;
600 if (!strupper_m(name)) {
601 DEBUG(5, ("Could not convert %s to uppercase\n", name));
602 continue;
604 id_map = idmap_rfc2307_find_map(maps, type, name);
605 if (!id_map) {
606 DEBUG(0, ("Could not find mapping entry for name %s\n",
607 name));
608 continue;
611 id_map->xid.id = id;
612 id_map->status = ID_MAPPED;
617 * Map sids to names and then to unixids.
619 static NTSTATUS idmap_rfc2307_sids_to_unixids(struct idmap_domain *dom,
620 struct id_map **ids)
622 struct idmap_rfc2307_context *ctx;
623 TALLOC_CTX *mem_ctx;
624 struct idmap_rfc2307_map *int_maps;
625 int cnt_usr = 0, cnt_grp = 0, idx = 0, bidx = 0;
626 char *fltr_usr = NULL, *fltr_grp = NULL;
627 NTSTATUS ret;
628 int i;
630 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
631 mem_ctx = talloc_new(talloc_tos());
632 if (!mem_ctx) {
633 return NT_STATUS_NO_MEMORY;
636 if (ctx->check_connection) {
637 ret = ctx->check_connection(dom);
638 if (!NT_STATUS_IS_OK(ret)) {
639 goto out;
643 for (i = 0; ids[i]; i++);
644 int_maps = talloc_zero_array(mem_ctx, struct idmap_rfc2307_map, i);
645 if (!int_maps) {
646 ret = NT_STATUS_NO_MEMORY;
647 goto out;
650 ret = idmap_rfc_2307_sids_to_names(mem_ctx, ids, int_maps, ctx);
651 if (!NT_STATUS_IS_OK(ret)) {
652 goto out;
655 again:
656 if (!fltr_usr) {
657 /* prepare new user query, see getpwuid() in RFC2307 */
658 fltr_usr = talloc_asprintf(mem_ctx,
659 "(&(objectClass=posixAccount)(|");
662 if (!fltr_grp) {
663 /* prepare new group query, see getgrgid() in RFC2307 */
664 fltr_grp = talloc_asprintf(mem_ctx,
665 "(&(objectClass=posixGroup)(|");
668 if (!fltr_usr || !fltr_grp) {
669 ret = NT_STATUS_NO_MEMORY;
670 goto out;
673 while (cnt_usr < IDMAP_LDAP_MAX_IDS &&
674 cnt_grp < IDMAP_LDAP_MAX_IDS && ids[idx]) {
675 struct id_map *id = ids[idx];
676 struct idmap_rfc2307_map *map = &int_maps[idx];
678 switch(id->xid.type) {
679 case ID_TYPE_UID:
680 fltr_usr = talloc_asprintf_append_buffer(fltr_usr,
681 "(%s=%s)", (ctx->user_cn ? "cn" : "uid"),
682 map->name);
683 cnt_usr++;
684 break;
686 case ID_TYPE_GID:
687 fltr_grp = talloc_asprintf_append_buffer(fltr_grp,
688 "(cn=%s)", map->name);
689 cnt_grp++;
690 break;
692 default:
693 DEBUG(10, ("Nothing to do for SID %s, "
694 "previous name lookup failed\n",
695 sid_string_dbg(map->map->sid)));
698 if (!fltr_usr || !fltr_grp) {
699 ret = NT_STATUS_NO_MEMORY;
700 goto out;
703 idx++;
706 if (cnt_usr == IDMAP_LDAP_MAX_IDS || (cnt_usr != 0 && !ids[idx])) {
707 const char *attrs[] = { NULL, /* uid or cn */
708 "uidNumber",
709 NULL };
710 LDAPMessage *result;
712 fltr_usr = talloc_strdup_append(fltr_usr, "))");
713 if (!fltr_usr) {
714 ret = NT_STATUS_NO_MEMORY;
715 goto out;
718 attrs[0] = ctx->user_cn ? "cn" : "uid";
719 ret = ctx->search(ctx, ctx->bind_path_user, fltr_usr, attrs,
720 &result);
721 if (!NT_STATUS_IS_OK(ret)) {
722 goto out;
725 idmap_rfc2307_map_xid_results(ctx, mem_ctx, &ids[bidx],
726 int_maps, result, dom,
727 attrs, ID_TYPE_UID);
729 cnt_usr = 0;
730 TALLOC_FREE(fltr_usr);
733 if (cnt_grp == IDMAP_LDAP_MAX_IDS || (cnt_grp != 0 && !ids[idx])) {
734 const char *attrs[] = {"cn", "gidNumber", NULL };
735 LDAPMessage *result;
737 fltr_grp = talloc_strdup_append(fltr_grp, "))");
738 if (!fltr_grp) {
739 ret = NT_STATUS_NO_MEMORY;
740 goto out;
743 ret = ctx->search(ctx, ctx->bind_path_group, fltr_grp, attrs,
744 &result);
745 if (!NT_STATUS_IS_OK(ret)) {
746 goto out;
749 idmap_rfc2307_map_xid_results(ctx, mem_ctx, &ids[bidx],
750 int_maps, result, dom,
751 attrs, ID_TYPE_GID);
752 cnt_grp = 0;
753 TALLOC_FREE(fltr_grp);
756 if (ids[idx]) {
757 goto again;
760 ret = NT_STATUS_OK;
762 out:
763 talloc_free(mem_ctx);
764 return ret;
767 static int idmap_rfc2307_context_destructor(struct idmap_rfc2307_context *ctx)
769 if (ctx->ads != NULL) {
770 /* we own this ADS_STRUCT so make sure it goes away */
771 ctx->ads->is_mine = True;
772 ads_destroy( &ctx->ads );
773 ctx->ads = NULL;
776 if (ctx->smbldap_state != NULL) {
777 smbldap_free_struct(&ctx->smbldap_state);
780 return 0;
783 static NTSTATUS idmap_rfc2307_initialize(struct idmap_domain *domain)
785 struct idmap_rfc2307_context *ctx;
786 char *cfg_opt;
787 const char *bind_path_user, *bind_path_group, *ldap_server;
788 NTSTATUS status;
790 ctx = talloc_zero(domain, struct idmap_rfc2307_context);
791 if (ctx == NULL) {
792 return NT_STATUS_NO_MEMORY;
794 talloc_set_destructor(ctx, idmap_rfc2307_context_destructor);
796 cfg_opt = talloc_asprintf(ctx, "idmap config %s", domain->name);
797 if (cfg_opt == NULL) {
798 status = NT_STATUS_NO_MEMORY;
799 goto err;
802 bind_path_user = lp_parm_const_string(-1, cfg_opt, "bind_path_user",
803 NULL);
804 if (bind_path_user) {
805 ctx->bind_path_user = talloc_strdup(ctx, bind_path_user);
806 if (ctx->bind_path_user == NULL) {
807 status = NT_STATUS_NO_MEMORY;
808 goto err;
810 } else {
811 status = NT_STATUS_INVALID_PARAMETER;
812 goto err;
815 bind_path_group = lp_parm_const_string(-1, cfg_opt, "bind_path_group",
816 NULL);
817 if (bind_path_group) {
818 ctx->bind_path_group = talloc_strdup(ctx, bind_path_group);
819 if (ctx->bind_path_group == NULL) {
820 status = NT_STATUS_NO_MEMORY;
821 goto err;
823 } else {
824 status = NT_STATUS_INVALID_PARAMETER;
825 goto err;
828 ldap_server = lp_parm_const_string(-1, cfg_opt, "ldap_server", NULL);
829 if (!ldap_server) {
830 status = NT_STATUS_INVALID_PARAMETER;
831 goto err;
834 if (strcmp(ldap_server, "stand-alone") == 0) {
835 status = idmap_rfc2307_init_ldap(ctx, domain, cfg_opt);
837 } else if (strcmp(ldap_server, "ad") == 0) {
838 status = idmap_rfc2307_init_ads(ctx, cfg_opt);
840 } else {
841 status = NT_STATUS_INVALID_PARAMETER;
844 if (!NT_STATUS_IS_OK(status)) {
845 goto err;
848 ctx->cn_realm = lp_parm_bool(-1, cfg_opt, "cn_realm", false);
849 ctx->user_cn = lp_parm_bool(-1, cfg_opt, "user_cn", false);
851 domain->private_data = ctx;
852 talloc_free(cfg_opt);
853 return NT_STATUS_OK;
855 err:
856 talloc_free(cfg_opt);
857 talloc_free(ctx);
858 return status;
861 static struct idmap_methods rfc2307_methods = {
862 .init = idmap_rfc2307_initialize,
863 .unixids_to_sids = idmap_rfc2307_unixids_to_sids,
864 .sids_to_unixids = idmap_rfc2307_sids_to_unixids,
867 NTSTATUS idmap_rfc2307_init(void)
869 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "rfc2307",
870 &rfc2307_methods);