r21585: Start syncing the monster that will become 3.0.25pre1
[Samba.git] / source / nsswitch / idmap_ad.c
blobfee53a0539ed7c00c01a079365bc1c6e2fd763e4
1 /*
2 * idmap_ad: map between Active Directory and RFC 2307 or "Services for Unix" (SFU) Accounts
4 * Unix SMB/CIFS implementation.
6 * Winbind ADS backend functions
8 * Copyright (C) Andrew Tridgell 2001
9 * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
10 * Copyright (C) Gerald (Jerry) Carter 2004-2007
11 * Copyright (C) Luke Howard 2001-2004
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include "includes.h"
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_IDMAP
33 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
35 #define IDMAP_AD_MAX_IDS 30
36 #define CHECK_ALLOC_DONE(mem) do { \
37 if (!mem) { \
38 DEBUG(0, ("Out of memory!\n")); \
39 ret = NT_STATUS_NO_MEMORY; \
40 goto done; \
41 } \
42 } while (0)
44 struct idmap_ad_context {
45 uint32_t filter_low_id;
46 uint32_t filter_high_id;
49 NTSTATUS init_module(void);
51 static ADS_STRUCT *ad_idmap_ads = NULL;
52 static struct posix_schema *ad_schema = NULL;
53 static enum wb_posix_mapping ad_map_type = WB_POSIX_MAP_UNKNOWN;
55 /************************************************************************
56 ***********************************************************************/
58 static ADS_STRUCT *ad_idmap_cached_connection_internal(void)
60 ADS_STRUCT *ads;
61 ADS_STATUS status;
62 BOOL local = False;
63 fstring dc_name;
64 struct in_addr dc_ip;
66 if (ad_idmap_ads != NULL) {
68 time_t expire;
69 time_t now = time(NULL);
71 ads = ad_idmap_ads;
73 expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
75 /* check for a valid structure */
76 DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n",
77 (uint32)expire-(uint32)now, (uint32) expire, (uint32) now));
79 if ( ads->config.realm && (expire > time(NULL))) {
80 return ads;
81 } else {
82 /* we own this ADS_STRUCT so make sure it goes away */
83 DEBUG(7,("Deleting expired krb5 credential cache\n"));
84 ads->is_mine = True;
85 ads_destroy( &ads );
86 ads_kdestroy(WINBIND_CCACHE_NAME);
87 ad_idmap_ads = NULL;
88 TALLOC_FREE( ad_schema );
92 if (!local) {
93 /* we don't want this to affect the users ccache */
94 setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
97 if ( (ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL ) {
98 DEBUG(1,("ads_init failed\n"));
99 return NULL;
102 /* the machine acct password might have change - fetch it every time */
103 SAFE_FREE(ads->auth.password);
104 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
106 SAFE_FREE(ads->auth.realm);
107 ads->auth.realm = SMB_STRDUP(lp_realm());
109 /* setup server affinity */
111 get_dc_name( NULL, ads->auth.realm, dc_name, &dc_ip );
113 status = ads_connect(ads);
114 if (!ADS_ERR_OK(status)) {
115 DEBUG(1, ("ad_idmap_init: failed to connect to AD\n"));
116 ads_destroy(&ads);
117 return NULL;
120 ads->is_mine = False;
122 ad_idmap_ads = ads;
124 return ads;
127 /************************************************************************
128 ***********************************************************************/
130 static ADS_STRUCT *ad_idmap_cached_connection(void)
132 ADS_STRUCT *ads = ad_idmap_cached_connection_internal();
134 if ( !ads )
135 return NULL;
137 /* if we have a valid ADS_STRUCT and the schema model is
138 defined, then we can return here. */
140 if ( ad_schema )
141 return ads;
143 /* Otherwise, set the schema model */
145 if ( (ad_map_type == WB_POSIX_MAP_SFU) ||
146 (ad_map_type == WB_POSIX_MAP_RFC2307) )
148 ADS_STATUS schema_status;
150 schema_status = ads_check_posix_schema_mapping( NULL, ads, ad_map_type, &ad_schema);
151 if ( !ADS_ERR_OK(schema_status) ) {
152 DEBUG(2,("ad_idmap_cached_connection: Failed to obtain schema details!\n"));
153 return NULL;
157 return ads;
160 /************************************************************************
161 ***********************************************************************/
163 static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, const char *params)
165 struct idmap_ad_context *ctx;
166 char *config_option;
167 const char *range;
168 ADS_STRUCT *ads;
170 /* verify AD is reachable (not critical, we may just be offline at start) */
171 if ( (ads = ad_idmap_cached_connection()) == NULL ) {
172 DEBUG(1, ("WARNING: Could not init an AD connection! Mapping might not work.\n"));
175 if ( (ctx = talloc_zero(dom, struct idmap_ad_context)) == NULL ) {
176 DEBUG(0, ("Out of memory!\n"));
177 return NT_STATUS_NO_MEMORY;
180 if ( (config_option = talloc_asprintf(ctx, "idmap config %s", dom->name)) == NULL ) {
181 DEBUG(0, ("Out of memory!\n"));
182 talloc_free(ctx);
183 return NT_STATUS_NO_MEMORY;
186 /* load ranges */
187 range = lp_parm_const_string(-1, config_option, "range", NULL);
188 if (range && range[0]) {
189 if ((sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) ||
190 (ctx->filter_low_id > ctx->filter_high_id)) {
191 DEBUG(1, ("ERROR: invalid filter range [%s]", range));
192 ctx->filter_low_id = 0;
193 ctx->filter_high_id = 0;
197 /* idmap AD can work well only if it is the default module (trusts)
198 * with additional BUILTIN and alloc using TDB */
199 if ( ! dom->default_domain) {
200 DEBUG(1, ("WARNING: idmap_ad is not configured as the default domain.\n"
201 "For best results we suggest you to configure this module as\n"
202 "default and configure BULTIN to use idmap_tdb\n"
203 "ex: idmap domains = BUILTIN %s\n"
204 " idmap alloc config: range = 5000 - 9999\n"
205 " idmap config %s: default = yes\n"
206 " idmap config %s: backend = ad\n"
207 " idmap config %s: range = 10000 - 10000000 #this is optional\n"
208 "NOTE: make sure the ranges do not overlap\n",
209 dom->name, dom->name, dom->name, dom->name));
212 if ( !dom->readonly ) {
213 DEBUG(1, ("WARNING: forcing to readonly, as idmap_ad can't write on AD.\n"));
214 dom->readonly = true;
217 dom->private_data = ctx;
219 talloc_free(config_option);
221 return NT_STATUS_OK;
224 /************************************************************************
225 Search up to IDMAP_AD_MAX_IDS entries in maps for a match.
226 ***********************************************************************/
228 static struct id_map *find_map_by_id(struct id_map **maps, enum id_type type, uint32_t id)
230 int i;
232 for (i = 0; maps[i] && i<IDMAP_AD_MAX_IDS; i++) {
233 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
234 return maps[i];
238 return NULL;
241 /************************************************************************
242 Search up to IDMAP_AD_MAX_IDS entries in maps for a match
243 ***********************************************************************/
245 static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
247 int i;
249 for (i = 0; maps[i] && i<IDMAP_AD_MAX_IDS; i++) {
250 if (sid_equal(maps[i]->sid, sid)) {
251 return maps[i];
255 return NULL;
258 /************************************************************************
259 ***********************************************************************/
261 static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
263 NTSTATUS ret;
264 TALLOC_CTX *memctx;
265 struct idmap_ad_context *ctx;
266 ADS_STATUS rc;
267 ADS_STRUCT *ads;
268 const char *attrs[] = { "sAMAccountType",
269 "objectSid",
270 NULL, /* uidnumber */
271 NULL, /* gidnumber */
272 NULL };
273 LDAPMessage *res = NULL;
274 char *filter = NULL;
275 int idx = 0;
276 int bidx = 0;
277 int count;
278 int i;
279 char *u_filter = NULL;
280 char *g_filter = NULL;
282 ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
284 if ( (memctx = talloc_new(ctx)) == NULL ) {
285 DEBUG(0, ("Out of memory!\n"));
286 return NT_STATUS_NO_MEMORY;
289 if ( (ads = ad_idmap_cached_connection()) == NULL ) {
290 DEBUG(1, ("ADS uninitialized\n"));
291 ret = NT_STATUS_UNSUCCESSFUL;
292 goto done;
295 attrs[2] = ad_schema->posix_uidnumber_attr;
296 attrs[3] = ad_schema->posix_gidnumber_attr;
298 again:
299 bidx = idx;
300 for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
301 switch (ids[idx]->xid.type) {
302 case ID_TYPE_UID:
303 if ( ! u_filter) {
304 u_filter = talloc_asprintf(memctx, "(&(|"
305 "(sAMAccountType=%d)"
306 "(sAMAccountType=%d)"
307 "(sAMAccountType=%d))(|",
308 ATYPE_NORMAL_ACCOUNT,
309 ATYPE_WORKSTATION_TRUST,
310 ATYPE_INTERDOMAIN_TRUST);
312 u_filter = talloc_asprintf_append(u_filter, "(%s=%lu)",
313 ad_schema->posix_uidnumber_attr,
314 (unsigned long)ids[idx]->xid.id);
315 CHECK_ALLOC_DONE(u_filter);
316 break;
318 case ID_TYPE_GID:
319 if ( ! g_filter) {
320 g_filter = talloc_asprintf(memctx, "(&(|"
321 "(sAMAccountType=%d)"
322 "(sAMAccountType=%d))(|",
323 ATYPE_SECURITY_GLOBAL_GROUP,
324 ATYPE_SECURITY_LOCAL_GROUP);
326 g_filter = talloc_asprintf_append(g_filter, "(%s=%lu)",
327 ad_schema->posix_gidnumber_attr,
328 (unsigned long)ids[idx]->xid.id);
329 CHECK_ALLOC_DONE(g_filter);
330 break;
332 default:
333 DEBUG(3, ("Unknown ID type\n"));
334 ids[idx]->status = ID_UNKNOWN;
335 continue;
338 filter = talloc_asprintf(memctx, "(|");
339 CHECK_ALLOC_DONE(filter);
340 if ( u_filter) {
341 filter = talloc_asprintf_append(filter, "%s))", u_filter);
342 CHECK_ALLOC_DONE(filter);
343 TALLOC_FREE(u_filter);
345 if ( g_filter) {
346 filter = talloc_asprintf_append(filter, "%s))", g_filter);
347 CHECK_ALLOC_DONE(filter);
348 TALLOC_FREE(g_filter);
350 filter = talloc_asprintf_append(filter, ")");
351 CHECK_ALLOC_DONE(filter);
352 DEBUG(10, ("Filter: [%s]\n", filter));
353 rc = ads_search_retry(ads, &res, filter, attrs);
354 if (!ADS_ERR_OK(rc)) {
355 DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc)));
356 ret = NT_STATUS_UNSUCCESSFUL;
357 goto done;
360 if ( (count = ads_count_replies(ads, res)) == 0 ) {
361 DEBUG(10, ("No IDs found\n"));
364 for (i = 0; i < count; i++) {
365 LDAPMessage *entry = NULL;
366 DOM_SID sid;
367 enum id_type type;
368 struct id_map *map;
369 uint32_t id;
370 uint32_t atype;
372 if (i == 0) { /* first entry */
373 entry = ads_first_entry(ads, res);
374 } else { /* following ones */
375 entry = ads_next_entry(ads, entry);
377 if ( ! entry) {
378 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
379 continue;
382 /* first check if the SID is present */
383 if (!ads_pull_sid(ads, entry, "objectSid", &sid)) {
384 DEBUG(2, ("Could not retrieve SID from entry\n"));
385 continue;
388 /* get type */
389 if (!ads_pull_uint32(ads, entry, "sAMAccountType", &atype)) {
390 DEBUG(1, ("could not get SAM account type\n"));
391 continue;
394 switch (atype & 0xF0000000) {
395 case ATYPE_SECURITY_GLOBAL_GROUP:
396 case ATYPE_SECURITY_LOCAL_GROUP:
397 type = ID_TYPE_GID;
398 break;
399 case ATYPE_NORMAL_ACCOUNT:
400 case ATYPE_WORKSTATION_TRUST:
401 case ATYPE_INTERDOMAIN_TRUST:
402 type = ID_TYPE_UID;
403 break;
404 default:
405 DEBUG(1, ("unrecognized SAM account type %08x\n", atype));
406 continue;
409 if (!ads_pull_uint32(ads, entry, (type==ID_TYPE_UID) ?
410 ad_schema->posix_uidnumber_attr :
411 ad_schema->posix_gidnumber_attr,
412 &id))
414 DEBUG(1, ("Could not get unix ID\n"));
415 continue;
418 if ((id == 0) ||
419 (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
420 (ctx->filter_high_id && (id > ctx->filter_high_id))) {
421 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
422 id, ctx->filter_low_id, ctx->filter_high_id));
423 continue;
426 map = find_map_by_id(&ids[bidx], type, id);
427 if (!map) {
428 DEBUG(2, ("WARNING: couldn't match result with requested ID\n"));
429 continue;
432 sid_copy(map->sid, &sid);
434 /* mapped */
435 map->status = ID_MAPPED;
437 DEBUG(10, ("Mapped %s -> %lu (%d)\n",
438 sid_string_static(map->sid),
439 (unsigned long)map->xid.id,
440 map->xid.type));
443 if (res) {
444 ads_msgfree(ads, res);
447 if (ids[idx]) { /* still some values to map */
448 goto again;
451 ret = NT_STATUS_OK;
453 /* mark all unknown ones as unmapped */
454 for (i = 0; ids[i]; i++) {
455 if (ids[i]->status == ID_UNKNOWN)
456 ids[i]->status = ID_UNMAPPED;
459 done:
460 talloc_free(memctx);
461 return ret;
464 /************************************************************************
465 ***********************************************************************/
467 static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
469 NTSTATUS ret;
470 TALLOC_CTX *memctx;
471 struct idmap_ad_context *ctx;
472 ADS_STATUS rc;
473 ADS_STRUCT *ads;
474 const char *attrs[] = { "sAMAccountType",
475 "objectSid",
476 NULL, /* attr_uidnumber */
477 NULL, /* attr_gidnumber */
478 NULL };
479 LDAPMessage *res = NULL;
480 char *filter = NULL;
481 int idx = 0;
482 int bidx = 0;
483 int count;
484 int i;
485 char *sidstr;
487 ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
489 if ( (memctx = talloc_new(ctx)) == NULL ) {
490 DEBUG(0, ("Out of memory!\n"));
491 return NT_STATUS_NO_MEMORY;
494 if ( (ads = ad_idmap_cached_connection()) == NULL ) {
495 DEBUG(1, ("ADS uninitialized\n"));
496 ret = NT_STATUS_UNSUCCESSFUL;
497 goto done;
500 attrs[2] = ad_schema->posix_uidnumber_attr;
501 attrs[3] = ad_schema->posix_gidnumber_attr;
503 again:
504 filter = talloc_asprintf(memctx, "(&(|"
505 "(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)" /* user account types */
506 "(sAMAccountType=%d)(sAMAccountType=%d)" /* group account types */
507 ")(|",
508 ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
509 ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP);
511 CHECK_ALLOC_DONE(filter);
513 bidx = idx;
514 for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
516 sidstr = sid_binstring(ids[idx]->sid);
517 filter = talloc_asprintf_append(filter, "(objectSid=%s)", sidstr);
519 free(sidstr);
520 CHECK_ALLOC_DONE(filter);
522 filter = talloc_asprintf_append(filter, "))");
523 CHECK_ALLOC_DONE(filter);
524 DEBUG(10, ("Filter: [%s]\n", filter));
526 rc = ads_search_retry(ads, &res, filter, attrs);
527 if (!ADS_ERR_OK(rc)) {
528 DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc)));
529 ret = NT_STATUS_UNSUCCESSFUL;
530 goto done;
533 if ( (count = ads_count_replies(ads, res)) == 0 ) {
534 DEBUG(10, ("No IDs found\n"));
537 for (i = 0; i < count; i++) {
538 LDAPMessage *entry = NULL;
539 DOM_SID sid;
540 enum id_type type;
541 struct id_map *map;
542 uint32_t id;
543 uint32_t atype;
545 if (i == 0) { /* first entry */
546 entry = ads_first_entry(ads, res);
547 } else { /* following ones */
548 entry = ads_next_entry(ads, entry);
550 if ( ! entry) {
551 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
552 continue;
555 /* first check if the SID is present */
556 if (!ads_pull_sid(ads, entry, "objectSid", &sid)) {
557 DEBUG(2, ("Could not retrieve SID from entry\n"));
558 continue;
561 map = find_map_by_sid(&ids[bidx], &sid);
562 if (!map) {
563 DEBUG(2, ("WARNING: couldn't match result with requested SID\n"));
564 continue;
567 /* get type */
568 if (!ads_pull_uint32(ads, entry, "sAMAccountType", &atype)) {
569 DEBUG(1, ("could not get SAM account type\n"));
570 continue;
573 switch (atype & 0xF0000000) {
574 case ATYPE_SECURITY_GLOBAL_GROUP:
575 case ATYPE_SECURITY_LOCAL_GROUP:
576 type = ID_TYPE_GID;
577 break;
578 case ATYPE_NORMAL_ACCOUNT:
579 case ATYPE_WORKSTATION_TRUST:
580 case ATYPE_INTERDOMAIN_TRUST:
581 type = ID_TYPE_UID;
582 break;
583 default:
584 DEBUG(1, ("unrecognized SAM account type %08x\n", atype));
585 continue;
588 if (!ads_pull_uint32(ads, entry, (type==ID_TYPE_UID) ?
589 ad_schema->posix_uidnumber_attr :
590 ad_schema->posix_gidnumber_attr,
591 &id))
593 DEBUG(1, ("Could not get unix ID\n"));
594 continue;
596 if ((id == 0) ||
597 (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
598 (ctx->filter_high_id && (id > ctx->filter_high_id))) {
599 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
600 id, ctx->filter_low_id, ctx->filter_high_id));
601 continue;
604 /* mapped */
605 map->xid.type = type;
606 map->xid.id = id;
607 map->status = ID_MAPPED;
609 DEBUG(10, ("Mapped %s -> %lu (%d)\n",
610 sid_string_static(map->sid),
611 (unsigned long)map->xid.id,
612 map->xid.type));
615 if (res) {
616 ads_msgfree(ads, res);
619 if (ids[idx]) { /* still some values to map */
620 goto again;
623 ret = NT_STATUS_OK;
625 /* mark all unknwon ones as unmapped */
626 for (i = 0; ids[i]; i++) {
627 if (ids[i]->status == ID_UNKNOWN)
628 ids[i]->status = ID_UNMAPPED;
631 done:
632 talloc_free(memctx);
633 return ret;
636 /************************************************************************
637 ***********************************************************************/
639 static NTSTATUS idmap_ad_close(struct idmap_domain *dom)
641 ADS_STRUCT *ads = ad_idmap_ads;
643 if (ads != NULL) {
644 /* we own this ADS_STRUCT so make sure it goes away */
645 ads->is_mine = True;
646 ads_destroy( &ads );
647 ad_idmap_ads = NULL;
650 TALLOC_FREE( ad_schema );
652 return NT_STATUS_OK;
656 * nss_info_{sfu,rfc2307}
659 /************************************************************************
660 Initialize the {sfu,rfc2307} state
661 ***********************************************************************/
663 static NTSTATUS nss_sfu_init( struct nss_domain_entry *e )
665 /* Sanity check if we have previously been called with a
666 different schema model */
668 if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) &&
669 (ad_map_type != WB_POSIX_MAP_SFU) )
671 DEBUG(0,("nss_sfu_init: Posix Map type has already been set. "
672 "Mixed schema models not supported!\n"));
673 return NT_STATUS_NOT_SUPPORTED;
676 ad_map_type = WB_POSIX_MAP_SFU;
678 if ( !ad_idmap_ads )
679 return idmap_ad_initialize( NULL, NULL );
681 return NT_STATUS_OK;
684 static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e )
686 /* Sanity check if we have previously been called with a
687 different schema model */
689 if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) &&
690 (ad_map_type != WB_POSIX_MAP_RFC2307) )
692 DEBUG(0,("nss_rfc2307_init: Posix Map type has already been set. "
693 "Mixed schema models not supported!\n"));
694 return NT_STATUS_NOT_SUPPORTED;
697 ad_map_type = WB_POSIX_MAP_RFC2307;
699 if ( !ad_idmap_ads )
700 return idmap_ad_initialize( NULL, NULL );
702 return NT_STATUS_OK;
706 /************************************************************************
707 ***********************************************************************/
708 static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e,
709 const DOM_SID *sid,
710 TALLOC_CTX *ctx,
711 ADS_STRUCT *ads,
712 LDAPMessage *msg,
713 char **homedir,
714 char **shell,
715 char **gecos,
716 uint32 *gid )
718 ADS_STRUCT *ads_internal = NULL;
720 /* We are assuming that the internal ADS_STRUCT is for the
721 same forest as the incoming *ads pointer */
723 ads_internal = ad_idmap_cached_connection();
725 if ( !ads_internal || !ad_schema )
726 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
728 if ( !homedir || !shell || !gecos )
729 return NT_STATUS_INVALID_PARAMETER;
731 *homedir = ads_pull_string( ads, ctx, msg, ad_schema->posix_homedir_attr );
732 *shell = ads_pull_string( ads, ctx, msg, ad_schema->posix_shell_attr );
733 *gecos = ads_pull_string( ads, ctx, msg, ad_schema->posix_gecos_attr );
735 if ( gid ) {
736 if ( !ads_pull_uint32(ads, msg, ad_schema->posix_gidnumber_attr, gid ) )
737 *gid = 0;
740 return NT_STATUS_OK;
743 /************************************************************************
744 ***********************************************************************/
746 static NTSTATUS nss_ad_close( void )
748 /* nothing to do. All memory is free()'d by the idmap close_fn() */
750 return NT_STATUS_OK;
753 /************************************************************************
754 Function dispatch tables for the idmap and nss plugins
755 ***********************************************************************/
757 static struct idmap_methods ad_methods = {
758 .init = idmap_ad_initialize,
759 .unixids_to_sids = idmap_ad_unixids_to_sids,
760 .sids_to_unixids = idmap_ad_sids_to_unixids,
761 .close_fn = idmap_ad_close
764 /* The SFU and RFC2307 NSS plugins share everything but the init
765 function which sets the intended schema model to use */
767 static struct nss_info_methods nss_rfc2307_methods = {
768 .init = nss_rfc2307_init,
769 .get_nss_info = nss_ad_get_info,
770 .close_fn = nss_ad_close
773 static struct nss_info_methods nss_sfu_methods = {
774 .init = nss_sfu_init,
775 .get_nss_info = nss_ad_get_info,
776 .close_fn = nss_ad_close
780 /************************************************************************
781 Initialize the plugins
782 ***********************************************************************/
784 NTSTATUS idmap_ad_init(void)
786 static NTSTATUS status_idmap_ad = NT_STATUS_UNSUCCESSFUL;
787 static NTSTATUS status_nss_rfc2307 = NT_STATUS_UNSUCCESSFUL;
788 static NTSTATUS status_nss_sfu = NT_STATUS_UNSUCCESSFUL;
790 /* Always register the AD method first in order to get the
791 idmap_domain interface called */
793 if ( !NT_STATUS_IS_OK(status_idmap_ad) ) {
794 status_idmap_ad = smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
795 "ad", &ad_methods);
796 if ( !NT_STATUS_IS_OK(status_idmap_ad) )
797 return status_idmap_ad;
800 if ( !NT_STATUS_IS_OK( status_nss_rfc2307 ) ) {
801 status_nss_rfc2307 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
802 "rfc2307", &nss_rfc2307_methods );
803 if ( !NT_STATUS_IS_OK(status_nss_rfc2307) )
804 return status_nss_rfc2307;
807 if ( !NT_STATUS_IS_OK( status_nss_sfu ) ) {
808 status_nss_sfu = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
809 "sfu", &nss_sfu_methods );
810 if ( !NT_STATUS_IS_OK(status_nss_sfu) )
811 return status_nss_sfu;
814 return NT_STATUS_OK;