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
12 * Copyright (C) Michael Adam 2008,2010
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see <http://www.gnu.org/licenses/>.
30 #include "../libds/common/flags.h"
32 #include "libads/ldap_schema.h"
36 #include "../libcli/ldap/ldap_ndr.h"
37 #include "../libcli/security/security.h"
40 #define DBGC_CLASS DBGC_IDMAP
42 #define CHECK_ALLOC_DONE(mem) do { \
44 DEBUG(0, ("Out of memory!\n")); \
45 ret = NT_STATUS_NO_MEMORY; \
50 struct idmap_ad_context
{
52 struct posix_schema
*ad_schema
;
53 enum wb_posix_mapping ad_map_type
; /* WB_POSIX_MAP_UNKNOWN */
56 /************************************************************************
57 ***********************************************************************/
59 static ADS_STATUS
ad_idmap_cached_connection_internal(struct idmap_domain
*dom
)
64 struct sockaddr_storage dc_ip
;
65 struct idmap_ad_context
*ctx
;
66 char *ldap_server
= NULL
;
68 struct winbindd_domain
*wb_dom
;
70 DEBUG(10, ("ad_idmap_cached_connection: called for domain '%s'\n",
73 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ad_context
);
75 ads_cached_connection_reuse(&ctx
->ads
);
76 if (ctx
->ads
!= NULL
) {
80 /* we don't want this to affect the users ccache */
81 setenv("KRB5CCNAME", WINBIND_CCACHE_NAME
, 1);
84 * At this point we only have the NetBIOS domain name.
85 * Check if we can get server nam and realm from SAF cache
86 * and the domain list.
88 ldap_server
= saf_fetch(dom
->name
);
89 DEBUG(10, ("ldap_server from saf cache: '%s'\n", ldap_server
?ldap_server
:""));
91 wb_dom
= find_domain_from_name_noinit(dom
->name
);
93 DEBUG(10, ("find_domain_from_name_noinit did not find domain '%s'\n",
97 DEBUG(10, ("find_domain_from_name_noinit found realm '%s' for "
98 " domain '%s'\n", wb_dom
->alt_name
, dom
->name
));
99 realm
= wb_dom
->alt_name
;
102 if ( (ads
= ads_init(realm
, dom
->name
, ldap_server
)) == NULL
) {
103 DEBUG(1,("ads_init failed\n"));
104 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
107 /* the machine acct password might have change - fetch it every time */
108 SAFE_FREE(ads
->auth
.password
);
109 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(), NULL
, NULL
);
111 SAFE_FREE(ads
->auth
.realm
);
112 ads
->auth
.realm
= SMB_STRDUP(lp_realm());
114 /* setup server affinity */
116 get_dc_name(dom
->name
, realm
, dc_name
, &dc_ip
);
118 status
= ads_connect(ads
);
119 if (!ADS_ERR_OK(status
)) {
120 DEBUG(1, ("ad_idmap_cached_connection_internal: failed to "
126 ads
->is_mine
= False
;
133 /************************************************************************
134 ***********************************************************************/
136 static ADS_STATUS
ad_idmap_cached_connection(struct idmap_domain
*dom
)
139 struct idmap_ad_context
* ctx
;
141 status
= ad_idmap_cached_connection_internal(dom
);
142 if (!ADS_ERR_OK(status
)) {
146 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ad_context
);
148 /* if we have a valid ADS_STRUCT and the schema model is
149 defined, then we can return here. */
151 if ( ctx
->ad_schema
) {
155 /* Otherwise, set the schema model */
157 if ( (ctx
->ad_map_type
== WB_POSIX_MAP_SFU
) ||
158 (ctx
->ad_map_type
== WB_POSIX_MAP_SFU20
) ||
159 (ctx
->ad_map_type
== WB_POSIX_MAP_RFC2307
) )
161 status
= ads_check_posix_schema_mapping(
162 ctx
, ctx
->ads
, ctx
->ad_map_type
, &ctx
->ad_schema
);
163 if ( !ADS_ERR_OK(status
) ) {
164 DEBUG(2,("ad_idmap_cached_connection: Failed to obtain schema details!\n"));
171 static int idmap_ad_context_destructor(struct idmap_ad_context
*ctx
)
173 if (ctx
->ads
!= NULL
) {
174 /* we own this ADS_STRUCT so make sure it goes away */
175 ctx
->ads
->is_mine
= True
;
176 ads_destroy( &ctx
->ads
);
182 /************************************************************************
183 ***********************************************************************/
185 static NTSTATUS
idmap_ad_initialize(struct idmap_domain
*dom
)
187 struct idmap_ad_context
*ctx
;
189 const char *schema_mode
= NULL
;
191 ctx
= talloc_zero(dom
, struct idmap_ad_context
);
193 DEBUG(0, ("Out of memory!\n"));
194 return NT_STATUS_NO_MEMORY
;
196 talloc_set_destructor(ctx
, idmap_ad_context_destructor
);
198 config_option
= talloc_asprintf(ctx
, "idmap config %s", dom
->name
);
199 if (config_option
== NULL
) {
200 DEBUG(0, ("Out of memory!\n"));
202 return NT_STATUS_NO_MEMORY
;
205 /* default map type */
206 ctx
->ad_map_type
= WB_POSIX_MAP_RFC2307
;
209 schema_mode
= lp_parm_const_string(-1, config_option
, "schema_mode", NULL
);
210 if ( schema_mode
&& schema_mode
[0] ) {
211 if ( strequal(schema_mode
, "sfu") )
212 ctx
->ad_map_type
= WB_POSIX_MAP_SFU
;
213 else if ( strequal(schema_mode
, "sfu20" ) )
214 ctx
->ad_map_type
= WB_POSIX_MAP_SFU20
;
215 else if ( strequal(schema_mode
, "rfc2307" ) )
216 ctx
->ad_map_type
= WB_POSIX_MAP_RFC2307
;
218 DEBUG(0,("idmap_ad_initialize: Unknown schema_mode (%s)\n",
222 dom
->private_data
= ctx
;
224 talloc_free(config_option
);
229 /************************************************************************
230 ***********************************************************************/
232 static NTSTATUS
idmap_ad_unixids_to_sids(struct idmap_domain
*dom
, struct id_map
**ids
)
236 struct idmap_ad_context
*ctx
;
238 const char *attrs
[] = { "sAMAccountType",
240 NULL
, /* uidnumber */
241 NULL
, /* gidnumber */
243 LDAPMessage
*res
= NULL
;
244 LDAPMessage
*entry
= NULL
;
250 char *u_filter
= NULL
;
251 char *g_filter
= NULL
;
253 /* initialize the status to avoid suprise */
254 for (i
= 0; ids
[i
]; i
++) {
255 ids
[i
]->status
= ID_UNKNOWN
;
258 /* Only do query if we are online */
259 if (idmap_is_offline()) {
260 return NT_STATUS_FILE_IS_OFFLINE
;
263 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ad_context
);
265 if ( (memctx
= talloc_new(ctx
)) == NULL
) {
266 DEBUG(0, ("Out of memory!\n"));
267 return NT_STATUS_NO_MEMORY
;
270 rc
= ad_idmap_cached_connection(dom
);
271 if (!ADS_ERR_OK(rc
)) {
272 DEBUG(1, ("ADS uninitialized: %s\n", ads_errstr(rc
)));
273 ret
= NT_STATUS_UNSUCCESSFUL
;
274 /* ret = ads_ntstatus(rc); */
278 attrs
[2] = ctx
->ad_schema
->posix_uidnumber_attr
;
279 attrs
[3] = ctx
->ad_schema
->posix_gidnumber_attr
;
283 for (i
= 0; (i
< IDMAP_LDAP_MAX_IDS
) && ids
[idx
]; i
++, idx
++) {
284 switch (ids
[idx
]->xid
.type
) {
287 u_filter
= talloc_asprintf(memctx
, "(&(|"
288 "(sAMAccountType=%d)"
289 "(sAMAccountType=%d)"
290 "(sAMAccountType=%d))(|",
291 ATYPE_NORMAL_ACCOUNT
,
292 ATYPE_WORKSTATION_TRUST
,
293 ATYPE_INTERDOMAIN_TRUST
);
295 u_filter
= talloc_asprintf_append_buffer(u_filter
, "(%s=%lu)",
296 ctx
->ad_schema
->posix_uidnumber_attr
,
297 (unsigned long)ids
[idx
]->xid
.id
);
298 CHECK_ALLOC_DONE(u_filter
);
303 g_filter
= talloc_asprintf(memctx
, "(&(|"
304 "(sAMAccountType=%d)"
305 "(sAMAccountType=%d))(|",
306 ATYPE_SECURITY_GLOBAL_GROUP
,
307 ATYPE_SECURITY_LOCAL_GROUP
);
309 g_filter
= talloc_asprintf_append_buffer(g_filter
, "(%s=%lu)",
310 ctx
->ad_schema
->posix_gidnumber_attr
,
311 (unsigned long)ids
[idx
]->xid
.id
);
312 CHECK_ALLOC_DONE(g_filter
);
316 DEBUG(3, ("Error: mapping requested but Unknown ID type\n"));
317 ids
[idx
]->status
= ID_UNKNOWN
;
321 filter
= talloc_asprintf(memctx
, "(|");
322 CHECK_ALLOC_DONE(filter
);
324 filter
= talloc_asprintf_append_buffer(filter
, "%s))", u_filter
);
325 CHECK_ALLOC_DONE(filter
);
326 TALLOC_FREE(u_filter
);
329 filter
= talloc_asprintf_append_buffer(filter
, "%s))", g_filter
);
330 CHECK_ALLOC_DONE(filter
);
331 TALLOC_FREE(g_filter
);
333 filter
= talloc_asprintf_append_buffer(filter
, ")");
334 CHECK_ALLOC_DONE(filter
);
336 rc
= ads_search_retry(ctx
->ads
, &res
, filter
, attrs
);
337 if (!ADS_ERR_OK(rc
)) {
338 DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc
)));
339 ret
= NT_STATUS_UNSUCCESSFUL
;
343 if ( (count
= ads_count_replies(ctx
->ads
, res
)) == 0 ) {
344 DEBUG(10, ("No IDs found\n"));
348 for (i
= 0; (i
< count
) && entry
; i
++) {
355 if (i
== 0) { /* first entry */
356 entry
= ads_first_entry(ctx
->ads
, entry
);
357 } else { /* following ones */
358 entry
= ads_next_entry(ctx
->ads
, entry
);
362 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
366 /* first check if the SID is present */
367 if (!ads_pull_sid(ctx
->ads
, entry
, "objectSid", &sid
)) {
368 DEBUG(2, ("Could not retrieve SID from entry\n"));
373 if (!ads_pull_uint32(ctx
->ads
, entry
, "sAMAccountType", &atype
)) {
374 DEBUG(1, ("could not get SAM account type\n"));
378 switch (atype
& 0xF0000000) {
379 case ATYPE_SECURITY_GLOBAL_GROUP
:
380 case ATYPE_SECURITY_LOCAL_GROUP
:
383 case ATYPE_NORMAL_ACCOUNT
:
384 case ATYPE_WORKSTATION_TRUST
:
385 case ATYPE_INTERDOMAIN_TRUST
:
389 DEBUG(1, ("unrecognized SAM account type %08x\n", atype
));
393 if (!ads_pull_uint32(ctx
->ads
, entry
, (type
==ID_TYPE_UID
) ?
394 ctx
->ad_schema
->posix_uidnumber_attr
:
395 ctx
->ad_schema
->posix_gidnumber_attr
,
398 DEBUG(1, ("Could not get unix ID\n"));
402 if (!idmap_unix_id_is_in_range(id
, dom
)) {
403 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
404 id
, dom
->low_id
, dom
->high_id
));
408 map
= idmap_find_map_by_id(&ids
[bidx
], type
, id
);
410 DEBUG(2, ("WARNING: couldn't match result with requested ID\n"));
414 sid_copy(map
->sid
, &sid
);
417 map
->status
= ID_MAPPED
;
419 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map
->sid
),
420 (unsigned long)map
->xid
.id
,
425 ads_msgfree(ctx
->ads
, res
);
428 if (ids
[idx
]) { /* still some values to map */
434 /* mark all unknown/expired ones as unmapped */
435 for (i
= 0; ids
[i
]; i
++) {
436 if (ids
[i
]->status
!= ID_MAPPED
)
437 ids
[i
]->status
= ID_UNMAPPED
;
445 /************************************************************************
446 ***********************************************************************/
448 static NTSTATUS
idmap_ad_sids_to_unixids(struct idmap_domain
*dom
, struct id_map
**ids
)
452 struct idmap_ad_context
*ctx
;
454 const char *attrs
[] = { "sAMAccountType",
456 NULL
, /* attr_uidnumber */
457 NULL
, /* attr_gidnumber */
459 LDAPMessage
*res
= NULL
;
460 LDAPMessage
*entry
= NULL
;
468 /* initialize the status to avoid suprise */
469 for (i
= 0; ids
[i
]; i
++) {
470 ids
[i
]->status
= ID_UNKNOWN
;
473 /* Only do query if we are online */
474 if (idmap_is_offline()) {
475 return NT_STATUS_FILE_IS_OFFLINE
;
478 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ad_context
);
480 if ( (memctx
= talloc_new(ctx
)) == NULL
) {
481 DEBUG(0, ("Out of memory!\n"));
482 return NT_STATUS_NO_MEMORY
;
485 rc
= ad_idmap_cached_connection(dom
);
486 if (!ADS_ERR_OK(rc
)) {
487 DEBUG(1, ("ADS uninitialized: %s\n", ads_errstr(rc
)));
488 ret
= NT_STATUS_UNSUCCESSFUL
;
489 /* ret = ads_ntstatus(rc); */
493 if (ctx
->ad_schema
== NULL
) {
494 DEBUG(0, ("haven't got ctx->ad_schema ! \n"));
495 ret
= NT_STATUS_UNSUCCESSFUL
;
499 attrs
[2] = ctx
->ad_schema
->posix_uidnumber_attr
;
500 attrs
[3] = ctx
->ad_schema
->posix_gidnumber_attr
;
503 filter
= talloc_asprintf(memctx
, "(&(|"
504 "(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)" /* user account types */
505 "(sAMAccountType=%d)(sAMAccountType=%d)" /* group account types */
507 ATYPE_NORMAL_ACCOUNT
, ATYPE_WORKSTATION_TRUST
, ATYPE_INTERDOMAIN_TRUST
,
508 ATYPE_SECURITY_GLOBAL_GROUP
, ATYPE_SECURITY_LOCAL_GROUP
);
510 CHECK_ALLOC_DONE(filter
);
513 for (i
= 0; (i
< IDMAP_LDAP_MAX_IDS
) && ids
[idx
]; i
++, idx
++) {
515 ids
[idx
]->status
= ID_UNKNOWN
;
517 sidstr
= ldap_encode_ndr_dom_sid(talloc_tos(), ids
[idx
]->sid
);
518 filter
= talloc_asprintf_append_buffer(filter
, "(objectSid=%s)", sidstr
);
521 CHECK_ALLOC_DONE(filter
);
523 filter
= talloc_asprintf_append_buffer(filter
, "))");
524 CHECK_ALLOC_DONE(filter
);
525 DEBUG(10, ("Filter: [%s]\n", filter
));
527 rc
= ads_search_retry(ctx
->ads
, &res
, filter
, attrs
);
528 if (!ADS_ERR_OK(rc
)) {
529 DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc
)));
530 ret
= NT_STATUS_UNSUCCESSFUL
;
534 if ( (count
= ads_count_replies(ctx
->ads
, res
)) == 0 ) {
535 DEBUG(10, ("No IDs found\n"));
539 for (i
= 0; (i
< count
) && entry
; i
++) {
546 if (i
== 0) { /* first entry */
547 entry
= ads_first_entry(ctx
->ads
, entry
);
548 } else { /* following ones */
549 entry
= ads_next_entry(ctx
->ads
, entry
);
553 DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
557 /* first check if the SID is present */
558 if (!ads_pull_sid(ctx
->ads
, entry
, "objectSid", &sid
)) {
559 DEBUG(2, ("Could not retrieve SID from entry\n"));
563 map
= idmap_find_map_by_sid(&ids
[bidx
], &sid
);
565 DEBUG(2, ("WARNING: couldn't match result with requested SID\n"));
570 if (!ads_pull_uint32(ctx
->ads
, entry
, "sAMAccountType", &atype
)) {
571 DEBUG(1, ("could not get SAM account type\n"));
575 switch (atype
& 0xF0000000) {
576 case ATYPE_SECURITY_GLOBAL_GROUP
:
577 case ATYPE_SECURITY_LOCAL_GROUP
:
580 case ATYPE_NORMAL_ACCOUNT
:
581 case ATYPE_WORKSTATION_TRUST
:
582 case ATYPE_INTERDOMAIN_TRUST
:
586 DEBUG(1, ("unrecognized SAM account type %08x\n", atype
));
590 if (!ads_pull_uint32(ctx
->ads
, entry
, (type
==ID_TYPE_UID
) ?
591 ctx
->ad_schema
->posix_uidnumber_attr
:
592 ctx
->ad_schema
->posix_gidnumber_attr
,
595 DEBUG(1, ("Could not get unix ID\n"));
598 if (!idmap_unix_id_is_in_range(id
, dom
)) {
599 DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
600 id
, dom
->low_id
, dom
->high_id
));
605 map
->xid
.type
= type
;
607 map
->status
= ID_MAPPED
;
609 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map
->sid
),
610 (unsigned long)map
->xid
.id
,
615 ads_msgfree(ctx
->ads
, res
);
618 if (ids
[idx
]) { /* still some values to map */
624 /* mark all unknown/expired ones as unmapped */
625 for (i
= 0; ids
[i
]; i
++) {
626 if (ids
[i
]->status
!= ID_MAPPED
)
627 ids
[i
]->status
= ID_UNMAPPED
;
636 * nss_info_{sfu,sfu20,rfc2307}
639 /************************************************************************
640 Initialize the {sfu,sfu20,rfc2307} state
641 ***********************************************************************/
643 static const char *wb_posix_map_unknown_string
= "WB_POSIX_MAP_UNKNOWN";
644 static const char *wb_posix_map_template_string
= "WB_POSIX_MAP_TEMPLATE";
645 static const char *wb_posix_map_sfu_string
= "WB_POSIX_MAP_SFU";
646 static const char *wb_posix_map_sfu20_string
= "WB_POSIX_MAP_SFU20";
647 static const char *wb_posix_map_rfc2307_string
= "WB_POSIX_MAP_RFC2307";
648 static const char *wb_posix_map_unixinfo_string
= "WB_POSIX_MAP_UNIXINFO";
650 static const char *ad_map_type_string(enum wb_posix_mapping map_type
)
653 case WB_POSIX_MAP_TEMPLATE
:
654 return wb_posix_map_template_string
;
655 case WB_POSIX_MAP_SFU
:
656 return wb_posix_map_sfu_string
;
657 case WB_POSIX_MAP_SFU20
:
658 return wb_posix_map_sfu20_string
;
659 case WB_POSIX_MAP_RFC2307
:
660 return wb_posix_map_rfc2307_string
;
661 case WB_POSIX_MAP_UNIXINFO
:
662 return wb_posix_map_unixinfo_string
;
664 return wb_posix_map_unknown_string
;
668 static NTSTATUS
nss_ad_generic_init(struct nss_domain_entry
*e
,
669 enum wb_posix_mapping new_ad_map_type
)
671 struct idmap_domain
*dom
;
672 struct idmap_ad_context
*ctx
;
674 if (e
->state
!= NULL
) {
675 dom
= talloc_get_type(e
->state
, struct idmap_domain
);
677 dom
= talloc_zero(e
, struct idmap_domain
);
679 DEBUG(0, ("Out of memory!\n"));
680 return NT_STATUS_NO_MEMORY
;
685 if (e
->domain
!= NULL
) {
686 dom
->name
= talloc_strdup(dom
, e
->domain
);
687 if (dom
->name
== NULL
) {
688 DEBUG(0, ("Out of memory!\n"));
689 return NT_STATUS_NO_MEMORY
;
693 if (dom
->private_data
!= NULL
) {
694 ctx
= talloc_get_type(dom
->private_data
,
695 struct idmap_ad_context
);
697 ctx
= talloc_zero(dom
, struct idmap_ad_context
);
699 DEBUG(0, ("Out of memory!\n"));
700 return NT_STATUS_NO_MEMORY
;
702 ctx
->ad_map_type
= WB_POSIX_MAP_RFC2307
;
703 dom
->private_data
= ctx
;
706 if ((ctx
->ad_map_type
!= WB_POSIX_MAP_UNKNOWN
) &&
707 (ctx
->ad_map_type
!= new_ad_map_type
))
709 DEBUG(2, ("nss_ad_generic_init: "
710 "Warning: overriding previously set posix map type "
711 "%s for domain %s with map type %s.\n",
712 ad_map_type_string(ctx
->ad_map_type
),
714 ad_map_type_string(new_ad_map_type
)));
717 ctx
->ad_map_type
= new_ad_map_type
;
722 static NTSTATUS
nss_sfu_init( struct nss_domain_entry
*e
)
724 return nss_ad_generic_init(e
, WB_POSIX_MAP_SFU
);
727 static NTSTATUS
nss_sfu20_init( struct nss_domain_entry
*e
)
729 return nss_ad_generic_init(e
, WB_POSIX_MAP_SFU20
);
732 static NTSTATUS
nss_rfc2307_init( struct nss_domain_entry
*e
)
734 return nss_ad_generic_init(e
, WB_POSIX_MAP_RFC2307
);
738 /************************************************************************
739 ***********************************************************************/
741 static NTSTATUS
nss_ad_get_info( struct nss_domain_entry
*e
,
742 const struct dom_sid
*sid
,
744 const char **homedir
,
749 const char *attrs
[] = {NULL
, /* attr_homedir */
750 NULL
, /* attr_shell */
751 NULL
, /* attr_gecos */
752 NULL
, /* attr_gidnumber */
755 LDAPMessage
*msg_internal
= NULL
;
756 ADS_STATUS ads_status
= ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
757 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
759 struct idmap_domain
*dom
;
760 struct idmap_ad_context
*ctx
;
762 DEBUG(10, ("nss_ad_get_info called for sid [%s] in domain '%s'\n",
763 sid_string_dbg(sid
), e
->domain
?e
->domain
:"NULL"));
765 /* Only do query if we are online */
766 if (idmap_is_offline()) {
767 return NT_STATUS_FILE_IS_OFFLINE
;
770 dom
= talloc_get_type(e
->state
, struct idmap_domain
);
771 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ad_context
);
773 ads_status
= ad_idmap_cached_connection(dom
);
774 if (!ADS_ERR_OK(ads_status
)) {
775 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
778 if (!ctx
->ad_schema
) {
779 DEBUG(10, ("nss_ad_get_info: no ad_schema configured!\n"));
780 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
783 if (!sid
|| !homedir
|| !shell
|| !gecos
) {
784 return NT_STATUS_INVALID_PARAMETER
;
787 /* Have to do our own query */
789 DEBUG(10, ("nss_ad_get_info: no ads connection given, doing our "
792 attrs
[0] = ctx
->ad_schema
->posix_homedir_attr
;
793 attrs
[1] = ctx
->ad_schema
->posix_shell_attr
;
794 attrs
[2] = ctx
->ad_schema
->posix_gecos_attr
;
795 attrs
[3] = ctx
->ad_schema
->posix_gidnumber_attr
;
797 sidstr
= ldap_encode_ndr_dom_sid(mem_ctx
, sid
);
798 filter
= talloc_asprintf(mem_ctx
, "(objectSid=%s)", sidstr
);
802 nt_status
= NT_STATUS_NO_MEMORY
;
806 ads_status
= ads_search_retry(ctx
->ads
, &msg_internal
, filter
, attrs
);
807 if (!ADS_ERR_OK(ads_status
)) {
808 nt_status
= ads_ntstatus(ads_status
);
812 *homedir
= ads_pull_string(ctx
->ads
, mem_ctx
, msg_internal
, ctx
->ad_schema
->posix_homedir_attr
);
813 *shell
= ads_pull_string(ctx
->ads
, mem_ctx
, msg_internal
, ctx
->ad_schema
->posix_shell_attr
);
814 *gecos
= ads_pull_string(ctx
->ads
, mem_ctx
, msg_internal
, ctx
->ad_schema
->posix_gecos_attr
);
817 if (!ads_pull_uint32(ctx
->ads
, msg_internal
, ctx
->ad_schema
->posix_gidnumber_attr
, gid
))
821 nt_status
= NT_STATUS_OK
;
825 ads_msgfree(ctx
->ads
, msg_internal
);
831 /**********************************************************************
832 *********************************************************************/
834 static NTSTATUS
nss_ad_map_to_alias(TALLOC_CTX
*mem_ctx
,
835 struct nss_domain_entry
*e
,
839 const char *attrs
[] = {NULL
, /* attr_uid */
842 LDAPMessage
*msg
= NULL
;
843 ADS_STATUS ads_status
= ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
844 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
845 struct idmap_domain
*dom
;
846 struct idmap_ad_context
*ctx
= NULL
;
848 /* Check incoming parameters */
850 if ( !e
|| !e
->domain
|| !name
|| !*alias
) {
851 nt_status
= NT_STATUS_INVALID_PARAMETER
;
855 /* Only do query if we are online */
857 if (idmap_is_offline()) {
858 nt_status
= NT_STATUS_FILE_IS_OFFLINE
;
862 dom
= talloc_get_type(e
->state
, struct idmap_domain
);
863 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ad_context
);
865 ads_status
= ad_idmap_cached_connection(dom
);
866 if (!ADS_ERR_OK(ads_status
)) {
867 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
870 if (!ctx
->ad_schema
) {
871 nt_status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
875 attrs
[0] = ctx
->ad_schema
->posix_uid_attr
;
877 filter
= talloc_asprintf(mem_ctx
,
878 "(sAMAccountName=%s)",
881 nt_status
= NT_STATUS_NO_MEMORY
;
885 ads_status
= ads_search_retry(ctx
->ads
, &msg
, filter
, attrs
);
886 if (!ADS_ERR_OK(ads_status
)) {
887 nt_status
= ads_ntstatus(ads_status
);
891 *alias
= ads_pull_string(ctx
->ads
, mem_ctx
, msg
, ctx
->ad_schema
->posix_uid_attr
);
894 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
897 nt_status
= NT_STATUS_OK
;
901 talloc_destroy(filter
);
904 ads_msgfree(ctx
->ads
, msg
);
910 /**********************************************************************
911 *********************************************************************/
913 static NTSTATUS
nss_ad_map_from_alias( TALLOC_CTX
*mem_ctx
,
914 struct nss_domain_entry
*e
,
918 const char *attrs
[] = {"sAMAccountName",
921 LDAPMessage
*msg
= NULL
;
922 ADS_STATUS ads_status
= ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
923 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
925 struct idmap_domain
*dom
;
926 struct idmap_ad_context
*ctx
= NULL
;
928 /* Check incoming parameters */
930 if ( !alias
|| !name
) {
931 nt_status
= NT_STATUS_INVALID_PARAMETER
;
935 /* Only do query if we are online */
937 if (idmap_is_offline()) {
938 nt_status
= NT_STATUS_FILE_IS_OFFLINE
;
942 dom
= talloc_get_type(e
->state
, struct idmap_domain
);
943 ctx
= talloc_get_type(dom
->private_data
, struct idmap_ad_context
);
945 ads_status
= ad_idmap_cached_connection(dom
);
946 if (!ADS_ERR_OK(ads_status
)) {
947 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
950 if (!ctx
->ad_schema
) {
951 nt_status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
955 filter
= talloc_asprintf(mem_ctx
,
957 ctx
->ad_schema
->posix_uid_attr
,
960 nt_status
= NT_STATUS_NO_MEMORY
;
964 ads_status
= ads_search_retry(ctx
->ads
, &msg
, filter
, attrs
);
965 if (!ADS_ERR_OK(ads_status
)) {
966 nt_status
= ads_ntstatus(ads_status
);
970 username
= ads_pull_string(ctx
->ads
, mem_ctx
, msg
,
973 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
976 *name
= talloc_asprintf(mem_ctx
, "%s\\%s",
980 nt_status
= NT_STATUS_NO_MEMORY
;
984 nt_status
= NT_STATUS_OK
;
988 talloc_destroy(filter
);
991 ads_msgfree(ctx
->ads
, msg
);
997 /************************************************************************
998 Function dispatch tables for the idmap and nss plugins
999 ***********************************************************************/
1001 static struct idmap_methods ad_methods
= {
1002 .init
= idmap_ad_initialize
,
1003 .unixids_to_sids
= idmap_ad_unixids_to_sids
,
1004 .sids_to_unixids
= idmap_ad_sids_to_unixids
,
1007 /* The SFU and RFC2307 NSS plugins share everything but the init
1008 function which sets the intended schema model to use */
1010 static struct nss_info_methods nss_rfc2307_methods
= {
1011 .init
= nss_rfc2307_init
,
1012 .get_nss_info
= nss_ad_get_info
,
1013 .map_to_alias
= nss_ad_map_to_alias
,
1014 .map_from_alias
= nss_ad_map_from_alias
,
1017 static struct nss_info_methods nss_sfu_methods
= {
1018 .init
= nss_sfu_init
,
1019 .get_nss_info
= nss_ad_get_info
,
1020 .map_to_alias
= nss_ad_map_to_alias
,
1021 .map_from_alias
= nss_ad_map_from_alias
,
1024 static struct nss_info_methods nss_sfu20_methods
= {
1025 .init
= nss_sfu20_init
,
1026 .get_nss_info
= nss_ad_get_info
,
1027 .map_to_alias
= nss_ad_map_to_alias
,
1028 .map_from_alias
= nss_ad_map_from_alias
,
1033 /************************************************************************
1034 Initialize the plugins
1035 ***********************************************************************/
1037 NTSTATUS
samba_init_module(void)
1039 static NTSTATUS status_idmap_ad
= NT_STATUS_UNSUCCESSFUL
;
1040 static NTSTATUS status_nss_rfc2307
= NT_STATUS_UNSUCCESSFUL
;
1041 static NTSTATUS status_nss_sfu
= NT_STATUS_UNSUCCESSFUL
;
1042 static NTSTATUS status_nss_sfu20
= NT_STATUS_UNSUCCESSFUL
;
1044 /* Always register the AD method first in order to get the
1045 idmap_domain interface called */
1047 if ( !NT_STATUS_IS_OK(status_idmap_ad
) ) {
1048 status_idmap_ad
= smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION
,
1050 if ( !NT_STATUS_IS_OK(status_idmap_ad
) )
1051 return status_idmap_ad
;
1054 if ( !NT_STATUS_IS_OK( status_nss_rfc2307
) ) {
1055 status_nss_rfc2307
= smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION
,
1056 "rfc2307", &nss_rfc2307_methods
);
1057 if ( !NT_STATUS_IS_OK(status_nss_rfc2307
) )
1058 return status_nss_rfc2307
;
1061 if ( !NT_STATUS_IS_OK( status_nss_sfu
) ) {
1062 status_nss_sfu
= smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION
,
1063 "sfu", &nss_sfu_methods
);
1064 if ( !NT_STATUS_IS_OK(status_nss_sfu
) )
1065 return status_nss_sfu
;
1068 if ( !NT_STATUS_IS_OK( status_nss_sfu20
) ) {
1069 status_nss_sfu20
= smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION
,
1070 "sfu20", &nss_sfu20_methods
);
1071 if ( !NT_STATUS_IS_OK(status_nss_sfu20
) )
1072 return status_nss_sfu20
;
1075 return NT_STATUS_OK
;