s3-winbindd: Add new module idmap_rfc2307
[Samba/gebeck_regimport.git] / source3 / winbindd / idmap_rfc2307.c
blob2b7a593a15ca8b57407457e95c1ea32b84a7870d
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 return ads_ntstatus(status);
109 static NTSTATUS idmap_rfc2307_init_ads(struct idmap_rfc2307_context *ctx,
110 const char *cfg_opt)
112 const char *ldap_domain;
114 ctx->search = idmap_rfc2307_ads_search;
115 ctx->check_connection = idmap_rfc2307_ads_check_connection;
117 ldap_domain = lp_parm_const_string(-1, cfg_opt, "ldap_domain",
118 NULL);
119 if (ldap_domain) {
120 ctx->ldap_domain = talloc_strdup(ctx, ldap_domain);
121 if (ctx->ldap_domain == NULL) {
122 return NT_STATUS_NO_MEMORY;
126 return NT_STATUS_OK;
130 * backend function for LDAP queries through stand-alone LDAP server
133 static NTSTATUS idmap_rfc2307_ldap_search(struct idmap_rfc2307_context *ctx,
134 const char *bind_path,
135 const char *expr,
136 const char **attrs,
137 LDAPMessage **result)
139 int ret;
141 ret = smbldap_search(ctx->smbldap_state, bind_path, LDAP_SCOPE_SUBTREE,
142 expr, attrs, 0, result);
143 ctx->ldap = ctx->smbldap_state->ldap_struct;
145 if (ret == LDAP_SUCCESS) {
146 return NT_STATUS_OK;
149 return NT_STATUS_LDAP(ret);
152 static bool idmap_rfc2307_get_uint32(LDAP *ldap, LDAPMessage *entry,
153 const char *field, uint32 *value)
155 bool b;
156 char str[20];
158 b = smbldap_get_single_attribute(ldap, entry, field, str, sizeof(str));
160 if (b) {
161 *value = atoi(str);
164 return b;
167 static NTSTATUS idmap_rfc2307_init_ldap(struct idmap_rfc2307_context *ctx,
168 struct idmap_domain *dom,
169 const char *config_option)
171 NTSTATUS ret;
172 char *url;
173 char *secret = NULL;
174 const char *ldap_url, *user_dn, *ldap_realm;
175 TALLOC_CTX *mem_ctx = ctx;
177 ldap_url = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
178 if (!ldap_url) {
179 DEBUG(1, ("ERROR: missing idmap ldap url\n"));
180 return NT_STATUS_UNSUCCESSFUL;
183 url = talloc_strdup(talloc_tos(), ldap_url);
185 user_dn = lp_parm_const_string(-1, config_option, "ldap_user_dn", NULL);
186 if (user_dn) {
187 secret = idmap_fetch_secret("ldap", dom->name, user_dn);
188 if (!secret) {
189 ret = NT_STATUS_ACCESS_DENIED;
190 goto done;
194 /* assume anonymous if we don't have a specified user */
195 ret = smbldap_init(mem_ctx, winbind_event_context(), url,
196 (user_dn == NULL), user_dn, secret,
197 &ctx->smbldap_state);
198 SAFE_FREE(secret);
199 if (!NT_STATUS_IS_OK(ret)) {
200 DEBUG(1, ("ERROR: smbldap_init (%s) failed!\n", url));
201 goto done;
204 ctx->search = idmap_rfc2307_ldap_search;
206 if (ctx->cn_realm) {
207 ldap_realm = lp_parm_const_string(-1, config_option,
208 "ldap_realm", NULL);
209 if (!ldap_realm) {
210 DEBUG(1, ("ERROR: cn_realm set, "
211 "but ldap_realm is missing\n"));
212 ret = NT_STATUS_UNSUCCESSFUL;
213 goto done;
215 ctx->realm = talloc_strdup(mem_ctx, ldap_realm);
216 if (!ctx->realm) {
217 ret = NT_STATUS_NO_MEMORY;
221 done:
222 talloc_free(url);
223 return ret;
227 * common code for stand-alone LDAP and ADS
230 static void idmap_rfc2307_map_sid_results(struct idmap_rfc2307_context *ctx,
231 TALLOC_CTX *mem_ctx,
232 struct id_map **ids,
233 LDAPMessage *result,
234 const char *dom_name,
235 const char **attrs, int type)
237 int count, i;
238 LDAPMessage *entry;
240 count = ldap_count_entries(ctx->ldap, result);
242 for (i = 0; i < count; i++) {
243 char *name;
244 enum lsa_SidType lsa_type;
245 struct id_map *map;
246 uint32_t id;
247 bool b;
249 if (i == 0) {
250 entry = ldap_first_entry(ctx->ldap, result);
251 } else {
252 entry = ldap_next_entry(ctx->ldap, result);
254 if (!entry) {
255 DEBUG(2, ("Unable to fetch entry.\n"));
256 break;
259 name = smbldap_talloc_single_attribute(ctx->ldap, entry,
260 attrs[0], mem_ctx);
261 if (!name) {
262 DEBUG(1, ("Could not get user name\n"));
263 continue;
266 b = idmap_rfc2307_get_uint32(ctx->ldap, entry, attrs[1], &id);
267 if (!b) {
268 DEBUG(1, ("Could not pull id for record %s\n", name));
269 continue;
272 map = idmap_find_map_by_id(ids, type, id);
273 if (!map) {
274 DEBUG(1, ("Could not find id %d, name %s\n", id, name));
275 continue;
278 if (ctx->cn_realm) {
279 /* Strip @realm from user or group name */
280 char *delim;
282 delim = strchr(name, '@');
283 if (delim) {
284 *delim = '\0';
288 /* by default calls to winbindd are disabled
289 the following call will not recurse so this is safe */
290 (void)winbind_on();
291 /* Lookup name from PDC using lsa_lookup_names() */
292 b = winbind_lookup_name(dom_name, name, map->sid, &lsa_type);
293 (void)winbind_off();
295 if (!b) {
296 DEBUG(1, ("SID lookup failed for id %d, %s\n",
297 id, name));
298 continue;
301 if (type == ID_TYPE_UID && lsa_type != SID_NAME_USER) {
302 DEBUG(1, ("Wrong type %d for user name %s\n",
303 type, name));
304 continue;
307 if (type == ID_TYPE_GID && lsa_type != SID_NAME_DOM_GRP &&
308 lsa_type != SID_NAME_ALIAS &&
309 lsa_type != SID_NAME_WKN_GRP) {
310 DEBUG(1, ("Wrong type %d for group name %s\n",
311 type, name));
312 continue;
315 map->status = ID_MAPPED;
320 * Map unixids to names and then to sids.
322 static NTSTATUS idmap_rfc2307_unixids_to_sids(struct idmap_domain *dom,
323 struct id_map **ids)
325 struct idmap_rfc2307_context *ctx;
326 char *fltr_usr = NULL, *fltr_grp = NULL;
327 TALLOC_CTX *mem_ctx;
328 int cnt_usr = 0, cnt_grp = 0, idx = 0, bidx = 0;
329 LDAPMessage *result = NULL;
330 NTSTATUS ret;
332 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
333 mem_ctx = talloc_new(ctx);
334 if (!mem_ctx) {
335 return NT_STATUS_NO_MEMORY;
338 if (ctx->check_connection) {
339 ret = ctx->check_connection(dom);
340 if (!NT_STATUS_IS_OK(ret)) {
341 goto out;
345 again:
346 bidx = idx;
348 if (!fltr_usr) {
349 /* prepare new user query, see getpwuid() in RFC2307 */
350 fltr_usr = talloc_asprintf(mem_ctx,
351 "(&(objectClass=posixAccount)(|");
354 if (!fltr_grp) {
355 /* prepare new group query, see getgrgid() in RFC2307 */
356 fltr_grp = talloc_asprintf(mem_ctx,
357 "(&(objectClass=posixGroup)(|");
360 if (!fltr_usr || !fltr_grp) {
361 ret = NT_STATUS_NO_MEMORY;
362 goto out;
365 while (cnt_usr < IDMAP_LDAP_MAX_IDS &&
366 cnt_grp < IDMAP_LDAP_MAX_IDS && ids[idx]) {
368 switch (ids[idx]->xid.type) {
369 case ID_TYPE_UID:
370 fltr_usr = talloc_asprintf_append_buffer(fltr_usr,
371 "(uidNumber=%d)", ids[idx]->xid.id);
372 cnt_usr++;
373 break;
374 case ID_TYPE_GID:
375 fltr_grp = talloc_asprintf_append_buffer(fltr_grp,
376 "(gidNumber=%d))", ids[idx]->xid.id);
377 cnt_grp++;
378 break;
379 default:
380 DEBUG(3, ("Error: unknown ID type %d\n",
381 ids[idx]->xid.type));
382 ret = NT_STATUS_UNSUCCESSFUL;
383 goto out;
386 if (!fltr_usr || !fltr_grp) {
387 ret = NT_STATUS_NO_MEMORY;
388 goto out;
391 idx++;
394 if (cnt_usr == IDMAP_LDAP_MAX_IDS || (cnt_usr != 0 && !ids[idx])) {
395 const char *attrs[] = { NULL, /* uid or cn */
396 "uidNumber",
397 NULL };
399 fltr_usr = talloc_strdup_append(fltr_usr, "))");
400 if (!fltr_usr) {
401 ret = NT_STATUS_NO_MEMORY;
402 goto out;
405 attrs[0] = ctx->user_cn ? "cn" : "uid";
406 ret = ctx->search(ctx, ctx->bind_path_user, fltr_usr, attrs,
407 &result);
408 if (!NT_STATUS_IS_OK(ret)) {
409 goto out;
412 idmap_rfc2307_map_sid_results(ctx, mem_ctx, &ids[bidx], result,
413 dom->name, attrs, ID_TYPE_UID);
414 cnt_usr = 0;
415 TALLOC_FREE(fltr_usr);
418 if (cnt_grp == IDMAP_LDAP_MAX_IDS || (cnt_grp != 0 && !ids[idx])) {
419 const char *attrs[] = { "cn", "gidNumber", NULL };
421 fltr_grp = talloc_strdup_append(fltr_grp, "))");
422 if (!fltr_grp) {
423 ret = NT_STATUS_NO_MEMORY;
424 goto out;
426 ret = ctx->search(ctx, ctx->bind_path_group, fltr_grp, attrs,
427 &result);
428 if (!NT_STATUS_IS_OK(ret)) {
429 goto out;
432 idmap_rfc2307_map_sid_results(ctx, mem_ctx, &ids[bidx], result,
433 dom->name, attrs, ID_TYPE_GID);
434 cnt_grp = 0;
435 TALLOC_FREE(fltr_grp);
438 if (ids[idx]) {
439 goto again;
442 ret = NT_STATUS_OK;
444 out:
445 talloc_free(mem_ctx);
446 return ret;
449 struct idmap_rfc2307_map {
450 struct id_map *map;
451 const char *name;
452 enum id_type type;
456 * Lookup names for SIDS and store the data in the local mapping
457 * array.
459 static NTSTATUS idmap_rfc_2307_sids_to_names(TALLOC_CTX *mem_ctx,
460 struct id_map **ids,
461 struct idmap_rfc2307_map *maps,
462 struct idmap_rfc2307_context *ctx)
464 int i;
466 for (i = 0; ids[i]; i++) {
467 const char *domain, *name;
468 enum lsa_SidType lsa_type;
469 struct id_map *id = ids[i];
470 struct idmap_rfc2307_map *map = &maps[i];
471 bool b;
473 /* by default calls to winbindd are disabled
474 the following call will not recurse so this is safe */
475 (void)winbind_on();
476 b = winbind_lookup_sid(mem_ctx, ids[i]->sid, &domain, &name,
477 &lsa_type);
478 (void)winbind_off();
480 if (!b) {
481 DEBUG(1, ("Lookup sid %s failed.\n",
482 sid_string_dbg(ids[i]->sid)));
483 continue;
486 switch(lsa_type) {
487 case SID_NAME_USER:
488 id->xid.type = map->type = ID_TYPE_UID;
489 if (ctx->user_cn && ctx->cn_realm) {
490 name = talloc_asprintf(mem_ctx, "%s@%s",
491 name, ctx->realm);
493 id->xid.type = map->type = ID_TYPE_UID;
494 break;
496 case SID_NAME_DOM_GRP:
497 case SID_NAME_ALIAS:
498 case SID_NAME_WKN_GRP:
499 if (ctx->cn_realm) {
500 name = talloc_asprintf(mem_ctx, "%s@%s",
501 name, ctx->realm);
503 id->xid.type = map->type = ID_TYPE_GID;
504 break;
506 default:
507 DEBUG(1, ("Unknown lsa type %d for sid %s\n",
508 lsa_type, sid_string_dbg(id->sid)));
509 id->status = ID_UNMAPPED;
510 continue;
513 map->map = id;
514 id->status = ID_UNKNOWN;
515 map->name = strupper_talloc(mem_ctx, name);
517 if (!map->name) {
518 return NT_STATUS_NO_MEMORY;
522 return NT_STATUS_OK;
526 * Find id_map entry by looking up the name in the internal
527 * mapping array.
529 static struct id_map* idmap_rfc2307_find_map(struct idmap_rfc2307_map *maps,
530 enum id_type type,
531 const char *name)
533 int i;
535 DEBUG(10, ("Looking for name %s, type %d\n", name, type));
537 for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
538 if (maps[i].map == NULL) { /* end of the run */
539 return NULL;
541 DEBUG(10, ("Entry %d: name %s, type %d\n",
542 i, maps[i].name, maps[i].type));
543 if (type == maps[i].type && strcmp(name, maps[i].name) == 0) {
544 return maps[i].map;
548 return NULL;
551 static void idmap_rfc2307_map_xid_results(struct idmap_rfc2307_context *ctx,
552 TALLOC_CTX *mem_ctx,
553 struct id_map **ids,
554 struct idmap_rfc2307_map *maps,
555 LDAPMessage *result,
556 struct idmap_domain *dom,
557 const char **attrs, enum id_type type)
559 int count, i;
560 LDAPMessage *entry;
562 count = ldap_count_entries(ctx->ldap, result);
564 for (i = 0; i < count; i++) {
565 uint32_t id;
566 char *name;
567 bool b;
568 struct id_map *id_map;
570 if (i == 0) {
571 entry = ldap_first_entry(ctx->ldap, result);
572 } else {
573 entry = ldap_next_entry(ctx->ldap, result);
575 if (!entry) {
576 DEBUG(2, ("Unable to fetch entry.\n"));
577 break;
580 name = smbldap_talloc_single_attribute(ctx->ldap, entry,
581 attrs[0], mem_ctx);
582 if (!name) {
583 DEBUG(1, ("Could not get user name\n"));
584 continue;
587 b = idmap_rfc2307_get_uint32(ctx->ldap, entry, attrs[1], &id);
588 if (!b) {
589 DEBUG(5, ("Could not pull id for record %s\n", name));
590 continue;
593 if (!idmap_unix_id_is_in_range(id, dom)) {
594 DEBUG(5, ("Requested id (%u) out of range (%u - %u).\n",
595 id, dom->low_id, dom->high_id));
596 continue;
599 if (!strupper_m(name)) {
600 DEBUG(5, ("Could not convert %s to uppercase\n", name));
601 continue;
603 id_map = idmap_rfc2307_find_map(maps, type, name);
604 if (!id_map) {
605 DEBUG(0, ("Could not find mapping entry for name %s\n",
606 name));
607 continue;
610 id_map->xid.id = id;
611 id_map->status = ID_MAPPED;
616 * Map sids to names and then to unixids.
618 static NTSTATUS idmap_rfc2307_sids_to_unixids(struct idmap_domain *dom,
619 struct id_map **ids)
621 struct idmap_rfc2307_context *ctx;
622 TALLOC_CTX *mem_ctx;
623 struct idmap_rfc2307_map *int_maps;
624 int cnt_usr = 0, cnt_grp = 0, idx = 0, bidx = 0;
625 char *fltr_usr = NULL, *fltr_grp = NULL;
626 NTSTATUS ret;
627 int i;
629 ctx = talloc_get_type(dom->private_data, struct idmap_rfc2307_context);
630 mem_ctx = talloc_new(talloc_tos());
631 if (!mem_ctx) {
632 return NT_STATUS_NO_MEMORY;
635 if (ctx->check_connection) {
636 ret = ctx->check_connection(dom);
637 if (!NT_STATUS_IS_OK(ret)) {
638 goto out;
642 for (i = 0; ids[i]; i++);
643 int_maps = talloc_zero_array(mem_ctx, struct idmap_rfc2307_map, i);
644 if (!int_maps) {
645 ret = NT_STATUS_NO_MEMORY;
646 goto out;
649 ret = idmap_rfc_2307_sids_to_names(mem_ctx, ids, int_maps, ctx);
650 if (!NT_STATUS_IS_OK(ret)) {
651 goto out;
654 again:
655 if (!fltr_usr) {
656 /* prepare new user query, see getpwuid() in RFC2307 */
657 fltr_usr = talloc_asprintf(mem_ctx,
658 "(&(objectClass=posixAccount)(|");
661 if (!fltr_grp) {
662 /* prepare new group query, see getgrgid() in RFC2307 */
663 fltr_grp = talloc_asprintf(mem_ctx,
664 "(&(objectClass=posixGroup)(|");
667 if (!fltr_usr || !fltr_grp) {
668 ret = NT_STATUS_NO_MEMORY;
669 goto out;
672 while (cnt_usr < IDMAP_LDAP_MAX_IDS &&
673 cnt_grp < IDMAP_LDAP_MAX_IDS && ids[idx]) {
674 struct id_map *id = ids[idx];
675 struct idmap_rfc2307_map *map = &int_maps[idx];
677 switch(id->xid.type) {
678 case ID_TYPE_UID:
679 fltr_usr = talloc_asprintf_append_buffer(fltr_usr,
680 "(%s=%s)", (ctx->user_cn ? "cn" : "uid"),
681 map->name);
682 cnt_usr++;
683 break;
685 case ID_TYPE_GID:
686 fltr_grp = talloc_asprintf_append_buffer(fltr_grp,
687 "(cn=%s)", map->name);
688 cnt_grp++;
689 break;
691 default:
692 DEBUG(10, ("Nothing to do for SID %s, "
693 "previous name lookup failed\n",
694 sid_string_dbg(map->map->sid)));
697 if (!fltr_usr || !fltr_grp) {
698 ret = NT_STATUS_NO_MEMORY;
699 goto out;
702 idx++;
705 if (cnt_usr == IDMAP_LDAP_MAX_IDS || (cnt_usr != 0 && !ids[idx])) {
706 const char *attrs[] = { NULL, /* uid or cn */
707 "uidNumber",
708 NULL };
709 LDAPMessage *result;
711 fltr_usr = talloc_strdup_append(fltr_usr, "))");
712 if (!fltr_usr) {
713 ret = NT_STATUS_NO_MEMORY;
714 goto out;
717 attrs[0] = ctx->user_cn ? "cn" : "uid";
718 ret = ctx->search(ctx, ctx->bind_path_user, fltr_usr, attrs,
719 &result);
720 if (!NT_STATUS_IS_OK(ret)) {
721 goto out;
724 idmap_rfc2307_map_xid_results(ctx, mem_ctx, &ids[bidx],
725 int_maps, result, dom,
726 attrs, ID_TYPE_UID);
728 cnt_usr = 0;
729 TALLOC_FREE(fltr_usr);
732 if (cnt_grp == IDMAP_LDAP_MAX_IDS || (cnt_grp != 0 && !ids[idx])) {
733 const char *attrs[] = {"cn", "gidNumber", NULL };
734 LDAPMessage *result;
736 fltr_grp = talloc_strdup_append(fltr_grp, "))");
737 if (!fltr_grp) {
738 ret = NT_STATUS_NO_MEMORY;
739 goto out;
742 ret = ctx->search(ctx, ctx->bind_path_group, fltr_grp, attrs,
743 &result);
744 if (!NT_STATUS_IS_OK(ret)) {
745 goto out;
748 idmap_rfc2307_map_xid_results(ctx, mem_ctx, &ids[bidx],
749 int_maps, result, dom,
750 attrs, ID_TYPE_GID);
751 cnt_grp = 0;
752 TALLOC_FREE(fltr_grp);
755 if (ids[idx]) {
756 goto again;
759 ret = NT_STATUS_OK;
761 out:
762 talloc_free(mem_ctx);
763 return ret;
766 static int idmap_rfc2307_context_destructor(struct idmap_rfc2307_context *ctx)
768 if (ctx->ads != NULL) {
769 /* we own this ADS_STRUCT so make sure it goes away */
770 ctx->ads->is_mine = True;
771 ads_destroy( &ctx->ads );
772 ctx->ads = NULL;
775 if (ctx->smbldap_state != NULL) {
776 smbldap_free_struct(&ctx->smbldap_state);
779 return 0;
782 static NTSTATUS idmap_rfc2307_initialize(struct idmap_domain *domain)
784 struct idmap_rfc2307_context *ctx;
785 char *cfg_opt;
786 const char *bind_path_user, *bind_path_group, *ldap_server;
787 NTSTATUS status;
789 ctx = talloc_zero(domain, struct idmap_rfc2307_context);
790 if (ctx == NULL) {
791 return NT_STATUS_NO_MEMORY;
793 talloc_set_destructor(ctx, idmap_rfc2307_context_destructor);
795 cfg_opt = talloc_asprintf(ctx, "idmap config %s", domain->name);
796 if (cfg_opt == NULL) {
797 status = NT_STATUS_NO_MEMORY;
798 goto err;
801 bind_path_user = lp_parm_const_string(-1, cfg_opt, "bind_path_user",
802 NULL);
803 if (bind_path_user) {
804 ctx->bind_path_user = talloc_strdup(ctx, bind_path_user);
805 if (ctx->bind_path_user == NULL) {
806 status = NT_STATUS_NO_MEMORY;
807 goto err;
809 } else {
810 status = NT_STATUS_INVALID_PARAMETER;
811 goto err;
814 bind_path_group = lp_parm_const_string(-1, cfg_opt, "bind_path_group",
815 NULL);
816 if (bind_path_group) {
817 ctx->bind_path_group = talloc_strdup(ctx, bind_path_group);
818 if (ctx->bind_path_group == NULL) {
819 status = NT_STATUS_NO_MEMORY;
820 goto err;
822 } else {
823 status = NT_STATUS_INVALID_PARAMETER;
824 goto err;
827 ldap_server = lp_parm_const_string(-1, cfg_opt, "ldap_server", NULL);
828 if (!ldap_server) {
829 status = NT_STATUS_INVALID_PARAMETER;
830 goto err;
833 if (strcmp(ldap_server, "stand-alone") == 0) {
834 status = idmap_rfc2307_init_ldap(ctx, domain, cfg_opt);
836 } else if (strcmp(ldap_server, "ad") == 0) {
837 status = idmap_rfc2307_init_ads(ctx, cfg_opt);
839 } else {
840 status = NT_STATUS_INVALID_PARAMETER;
843 if (!NT_STATUS_IS_OK(status)) {
844 goto err;
847 ctx->cn_realm = lp_parm_bool(-1, cfg_opt, "cn_realm", false);
848 ctx->user_cn = lp_parm_bool(-1, cfg_opt, "user_cn", false);
850 domain->private_data = ctx;
851 talloc_free(cfg_opt);
852 return NT_STATUS_OK;
854 err:
855 talloc_free(cfg_opt);
856 talloc_free(ctx);
857 return status;
860 static struct idmap_methods rfc2307_methods = {
861 .init = idmap_rfc2307_initialize,
862 .unixids_to_sids = idmap_rfc2307_unixids_to_sids,
863 .sids_to_unixids = idmap_rfc2307_sids_to_unixids,
866 NTSTATUS idmap_rfc2307_init(void)
868 return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "rfc2307",
869 &rfc2307_methods);