2 * idmap_ad: map between Active Directory and RFC 2307 accounts
4 * Copyright (C) Volker Lendecke 2015
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "libsmb/namequery.h"
25 #include "tldap_util.h"
26 #include "tldap_tls_connect.h"
27 #include "tldap_gensec_bind.h"
29 #include "lib/param/param.h"
30 #include "auth/gensec/gensec.h"
31 #include "librpc/gen_ndr/ndr_netlogon.h"
32 #include "libads/ldap_schema_oids.h"
33 #include "../libds/common/flags.h"
34 #include "libcli/ldap/ldap_ndr.h"
35 #include "libcli/security/dom_sid.h"
36 #include "source3/libads/sitename_cache.h"
37 #include "source3/libads/kerberos_proto.h"
38 #include "source3/librpc/gen_ndr/ads.h"
39 #include "source3/lib/global_contexts.h"
42 struct idmap_ad_schema_names
;
44 struct idmap_ad_context
{
45 struct idmap_domain
*dom
;
46 struct tldap_context
*ld
;
47 struct idmap_ad_schema_names
*schema
;
48 const char *default_nc
;
50 bool unix_primary_group
;
53 struct ldb_context
*ldb
;
54 struct ldb_dn
**deny_ous
;
55 struct ldb_dn
**allow_ous
;
58 static NTSTATUS
idmap_ad_get_context(struct idmap_domain
*dom
,
59 struct idmap_ad_context
**pctx
);
61 static char *get_schema_path(TALLOC_CTX
*mem_ctx
, struct tldap_context
*ld
)
63 struct tldap_message
*rootdse
;
65 rootdse
= tldap_rootdse(ld
);
66 if (rootdse
== NULL
) {
70 return tldap_talloc_single_attribute(rootdse
, "schemaNamingContext",
74 static char *get_default_nc(TALLOC_CTX
*mem_ctx
, struct tldap_context
*ld
)
76 struct tldap_message
*rootdse
;
78 rootdse
= tldap_rootdse(ld
);
79 if (rootdse
== NULL
) {
83 return tldap_talloc_single_attribute(rootdse
, "defaultNamingContext",
87 struct idmap_ad_schema_names
{
96 static TLDAPRC
get_attrnames_by_oids(struct tldap_context
*ld
,
98 const char *schema_path
,
104 const char *attrs
[] = { "lDAPDisplayName", "attributeId" };
107 struct tldap_message
**msgs
;
110 filter
= talloc_strdup(mem_ctx
, "(|");
112 for (i
=0; i
<num_oids
; i
++) {
113 talloc_asprintf_addbuf(&filter
, "(attributeId=%s)", oids
[i
]);
115 talloc_asprintf_addbuf(&filter
, ")");
117 if (filter
== NULL
) {
118 return TLDAP_NO_MEMORY
;
121 rc
= tldap_search(ld
, schema_path
, TLDAP_SCOPE_SUB
, filter
,
122 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
123 0, 0, 0, mem_ctx
, &msgs
);;
125 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
129 for (i
=0; i
<num_oids
; i
++) {
133 num_msgs
= talloc_array_length(msgs
);
135 for (i
=0; i
<num_msgs
; i
++) {
136 struct tldap_message
*msg
= msgs
[i
];
140 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
141 /* Could be a TLDAP_RES_SEARCH_REFERENCE */
145 oid
= tldap_talloc_single_attribute(
146 msg
, "attributeId", msg
);
151 for (j
=0; j
<num_oids
; j
++) {
152 if (strequal(oid
, oids
[j
])) {
163 names
[j
] = tldap_talloc_single_attribute(
164 msg
, "lDAPDisplayName", mem_ctx
);
168 for (i
=0; i
<num_oids
; i
++) {
169 if (names
[i
] == NULL
) {
170 DBG_ERR("Failed to retrieve schema name for "
171 "oid [%s]. Schema mode is incorrect "
172 "for this domain.\n", oids
[i
]);
173 return TLDAP_FILTER_ERROR
;
177 return TLDAP_SUCCESS
;
180 static TLDAPRC
get_posix_schema_names(struct tldap_context
*ld
,
181 const char *schema_mode
,
183 struct idmap_ad_schema_names
**pschema
)
186 struct idmap_ad_schema_names
*schema
;
188 const char *oids_sfu
[] = {
189 ADS_ATTR_SFU_UIDNUMBER_OID
,
190 ADS_ATTR_SFU_GIDNUMBER_OID
,
191 ADS_ATTR_SFU_HOMEDIR_OID
,
192 ADS_ATTR_SFU_SHELL_OID
,
193 ADS_ATTR_SFU_GECOS_OID
,
196 const char *oids_sfu20
[] = {
197 ADS_ATTR_SFU20_UIDNUMBER_OID
,
198 ADS_ATTR_SFU20_GIDNUMBER_OID
,
199 ADS_ATTR_SFU20_HOMEDIR_OID
,
200 ADS_ATTR_SFU20_SHELL_OID
,
201 ADS_ATTR_SFU20_GECOS_OID
,
202 ADS_ATTR_SFU20_UID_OID
204 const char *oids_rfc2307
[] = {
205 ADS_ATTR_RFC2307_UIDNUMBER_OID
,
206 ADS_ATTR_RFC2307_GIDNUMBER_OID
,
207 ADS_ATTR_RFC2307_HOMEDIR_OID
,
208 ADS_ATTR_RFC2307_SHELL_OID
,
209 ADS_ATTR_RFC2307_GECOS_OID
,
210 ADS_ATTR_RFC2307_UID_OID
216 schema
= talloc(mem_ctx
, struct idmap_ad_schema_names
);
217 if (schema
== NULL
) {
218 return TLDAP_NO_MEMORY
;
221 schema_path
= get_schema_path(schema
, ld
);
222 if (schema_path
== NULL
) {
224 return TLDAP_NO_MEMORY
;
229 if ((schema_mode
!= NULL
) && (schema_mode
[0] != '\0')) {
230 if (strequal(schema_mode
, "sfu")) {
232 } else if (strequal(schema_mode
, "sfu20")) {
234 } else if (strequal(schema_mode
, "rfc2307" )) {
237 DBG_WARNING("Unknown schema mode %s\n", schema_mode
);
241 rc
= get_attrnames_by_oids(ld
, schema
, schema_path
, 6, oids
, names
);
242 TALLOC_FREE(schema_path
);
243 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
248 schema
->uid
= names
[0];
249 schema
->gid
= names
[1];
250 schema
->dir
= names
[2];
251 schema
->shell
= names
[3];
252 schema
->gecos
= names
[4];
253 schema
->name
= names
[5];
257 return TLDAP_SUCCESS
;
260 static void PRINTF_ATTRIBUTE(3, 0) idmap_ad_tldap_debug(
262 enum tldap_debug_level level
,
266 int samba_level
= -1;
269 case TLDAP_DEBUG_FATAL
:
270 samba_level
= DBGLVL_ERR
;
272 case TLDAP_DEBUG_ERROR
:
273 samba_level
= DBGLVL_ERR
;
275 case TLDAP_DEBUG_WARNING
:
276 samba_level
= DBGLVL_WARNING
;
278 case TLDAP_DEBUG_TRACE
:
279 samba_level
= DBGLVL_DEBUG
;
283 if (CHECK_DEBUGLVL(samba_level
)) {
287 ret
= vasprintf(&s
, fmt
, ap
);
291 DEBUG(samba_level
, ("idmap_ad_tldap: %s", s
));
296 static NTSTATUS
idmap_ad_get_tldap_ctx(TALLOC_CTX
*mem_ctx
,
298 struct tldap_context
**pld
)
300 struct netr_DsRGetDCNameInfo
*dcinfo
;
301 struct sockaddr_storage dcaddr
= {
302 .ss_family
= AF_UNSPEC
,
304 struct sockaddr_storage
*pdcaddr
= NULL
;
305 struct winbindd_domain
*creds_domain
= NULL
;
306 struct cli_credentials
*creds
;
307 struct loadparm_context
*lp_ctx
;
308 struct tldap_context
*ld
;
310 bool use_tls
= false;
311 bool use_starttls
= false;
313 uint32_t gensec_features
= 0;
314 char *sitename
= NULL
;
320 wrap_flags
= lp_client_ldap_sasl_wrapping();
322 if (wrap_flags
& ADS_AUTH_SASL_LDAPS
) {
325 } else if (wrap_flags
& ADS_AUTH_SASL_STARTTLS
) {
329 if (wrap_flags
& ADS_AUTH_SASL_SEAL
) {
330 gensec_features
|= GENSEC_FEATURE_SEAL
;
332 if (wrap_flags
& ADS_AUTH_SASL_SIGN
) {
333 gensec_features
|= GENSEC_FEATURE_SIGN
;
336 if (gensec_features
!= 0) {
337 gensec_features
|= GENSEC_FEATURE_LDAP_STYLE
;
340 status
= wb_dsgetdcname_gencache_get(mem_ctx
, domname
, &dcinfo
);
341 if (!NT_STATUS_IS_OK(status
)) {
342 DBG_DEBUG("Could not get dcinfo for %s: %s\n", domname
,
347 if (dcinfo
->dc_unc
== NULL
) {
349 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
351 if (dcinfo
->dc_unc
[0] == '\\') {
354 if (dcinfo
->dc_unc
[0] == '\\') {
358 ok
= resolve_name(dcinfo
->dc_unc
, &dcaddr
, 0x20, true);
360 DBG_DEBUG("Could not resolve name %s\n", dcinfo
->dc_unc
);
362 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
365 sitename
= sitename_fetch(talloc_tos(), lp_realm());
368 * create_local_private_krb5_conf_for_domain() can deal with
371 if (strequal(domname
, lp_realm()) || strequal(domname
, lp_workgroup()))
376 ok
= create_local_private_krb5_conf_for_domain(
377 lp_realm(), lp_workgroup(), sitename
, pdcaddr
);
378 TALLOC_FREE(sitename
);
380 DBG_DEBUG("Could not create private krb5.conf\n");
382 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
385 status
= open_socket_out(&dcaddr
, tcp_port
, 10000, &fd
);
386 if (!NT_STATUS_IS_OK(status
)) {
387 DBG_DEBUG("open_socket_out failed: %s\n", nt_errstr(status
));
392 ld
= tldap_context_create(dcinfo
, fd
);
394 DBG_DEBUG("tldap_context_create failed\n");
397 return NT_STATUS_NO_MEMORY
;
399 tldap_set_debug(ld
, idmap_ad_tldap_debug
, NULL
);
402 * Here we use or own machine account as
403 * we run as domain member.
405 creds_domain
= find_our_domain();
406 if (creds_domain
== NULL
) {
407 DBG_ERR("find_our_domain() returned NULL\n");
409 return NT_STATUS_INTERNAL_ERROR
;
411 status
= winbindd_get_trust_credentials(creds_domain
,
413 false, /* netlogon */
414 false, /* ipc_fallback */
416 if (!NT_STATUS_IS_OK(status
)) {
417 DBG_ERR("winbindd_get_trust_credentials(%s) failed - %s\n",
418 creds_domain
->name
, nt_errstr(status
));
423 lp_ctx
= loadparm_init_s3(dcinfo
, loadparm_s3_helpers());
424 if (lp_ctx
== NULL
) {
425 DBG_DEBUG("loadparm_init_s3 failed\n");
427 return NT_STATUS_NO_MEMORY
;
430 if (use_tls
&& !tldap_has_tls_tstream(ld
)) {
431 tldap_set_starttls_needed(ld
, use_starttls
);
433 rc
= tldap_tls_connect(ld
, lp_ctx
, dcinfo
->dc_unc
);
434 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
435 DBG_ERR("tldap_gensec_bind(%s) failed: %s\n",
437 tldap_errstr(dcinfo
, ld
, rc
));
439 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
443 rc
= tldap_gensec_bind(ld
, creds
, "ldap", dcinfo
->dc_unc
, NULL
, lp_ctx
,
445 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
446 DBG_DEBUG("tldap_gensec_bind failed: %s\n",
447 tldap_errstr(dcinfo
, ld
, rc
));
449 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
452 rc
= tldap_fetch_rootdse(ld
);
453 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
454 DBG_DEBUG("tldap_fetch_rootdse failed: %s\n",
455 tldap_errstr(dcinfo
, ld
, rc
));
457 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
460 *pld
= talloc_move(mem_ctx
, &ld
);
465 static int idmap_ad_context_destructor(struct idmap_ad_context
*ctx
)
467 if ((ctx
->dom
!= NULL
) && (ctx
->dom
->private_data
== ctx
)) {
468 ctx
->dom
->private_data
= NULL
;
473 static struct ldb_dn
**str_list_to_dns(TALLOC_CTX
*mem_ctx
,
475 struct ldb_context
*ldb
,
476 const char **strlist
)
478 size_t i
, num_dns
= str_list_length(strlist
);
480 struct ldb_dn
**dns
= NULL
;
482 dns
= talloc_array(mem_ctx
, struct ldb_dn
*, num_dns
);
488 dbgstr
= talloc_strdup(talloc_tos(), "");
490 for (i
= 0; i
< num_dns
; i
++) {
491 dns
[i
] = ldb_dn_new(dns
, ldb
, strlist
[i
]);
492 if (dns
[i
] == NULL
) {
493 DBG_WARNING("ldb_dn_new(%s) failed\n", strlist
[i
]);
497 talloc_asprintf_addbuf(
500 ldb_dn_get_extended_linearized(dbgstr
, dns
[i
], 1));
503 DBG_DEBUG("%s %s\n", dbgmsg
, dbgstr
);
509 static NTSTATUS
idmap_ad_context_create(TALLOC_CTX
*mem_ctx
,
510 struct idmap_domain
*dom
,
512 struct idmap_ad_context
**pctx
)
514 struct idmap_ad_context
*ctx
;
515 const char *schema_mode
;
516 const char **allow
= NULL
;
517 const char **deny
= NULL
;
521 ctx
= talloc_zero(mem_ctx
, struct idmap_ad_context
);
523 return NT_STATUS_NO_MEMORY
;
527 talloc_set_destructor(ctx
, idmap_ad_context_destructor
);
529 status
= idmap_ad_get_tldap_ctx(ctx
, domname
, &ctx
->ld
);
530 if (!NT_STATUS_IS_OK(status
)) {
531 DBG_DEBUG("idmap_ad_get_tldap_ctx failed: %s\n",
537 ctx
->default_nc
= get_default_nc(ctx
, ctx
->ld
);
538 if (ctx
->default_nc
== NULL
) {
539 DBG_DEBUG("No default nc\n");
544 ctx
->unix_primary_group
= idmap_config_bool(
545 domname
, "unix_primary_group", false);
546 ctx
->unix_nss_info
= idmap_config_bool(
547 domname
, "unix_nss_info", false);
549 schema_mode
= idmap_config_const_string(
550 domname
, "schema_mode", "rfc2307");
552 rc
= get_posix_schema_names(ctx
->ld
, schema_mode
, ctx
, &ctx
->schema
);
553 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
554 DBG_DEBUG("get_posix_schema_names failed: %s\n",
555 tldap_errstr(ctx
, ctx
->ld
, rc
));
557 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
560 deny
= idmap_config_string_list(domname
, "deny ous", NULL
);
561 allow
= idmap_config_string_list(domname
, "allow ous", NULL
);
563 if ((deny
!= NULL
) || (allow
!= NULL
)) {
564 int ret
= ldb_global_init();
566 status
= map_nt_error_from_unix(errno
);
567 DBG_WARNING("ldb_global_init() failed: %s\n",
573 ctx
->ldb
= ldb_init(ctx
, global_event_context());
574 if (ctx
->ldb
== NULL
) {
575 status
= map_nt_error_from_unix(errno
);
576 DBG_WARNING("ldb_init() failed: %s\n", strerror(errno
));
583 ctx
->deny_ous
= str_list_to_dns(ctx
, "Denying", ctx
->ldb
, deny
);
584 if (ctx
->deny_ous
== NULL
) {
585 DBG_DEBUG("str_list_to_dns failed\n");
587 return NT_STATUS_NO_MEMORY
;
593 str_list_to_dns(ctx
, "Allowing", ctx
->ldb
, allow
);
594 if (ctx
->allow_ous
== NULL
) {
595 DBG_DEBUG("str_list_to_dns failed\n");
597 return NT_STATUS_NO_MEMORY
;
605 static bool check_dn(struct ldb_dn
**dns
, struct ldb_dn
*dn
)
607 size_t i
, num_dns
= talloc_array_length(dns
);
609 for (i
= 0; i
< num_dns
; i
++) {
610 struct ldb_dn
*base
= dns
[i
];
611 int ret
= ldb_dn_compare_base(base
, dn
);
619 static bool idmap_ad_dn_filter(struct idmap_domain
*dom
, const char *dnstr
)
621 struct idmap_ad_context
*ctx
= NULL
;
622 struct ldb_dn
*dn
= NULL
;
626 status
= idmap_ad_get_context(dom
, &ctx
);
627 if (!NT_STATUS_IS_OK(status
)) {
628 DBG_DEBUG("idmap_ad_get_context failed: %s\n",
633 if ((ctx
->allow_ous
== NULL
) && (ctx
->deny_ous
== NULL
)) {
640 dn
= ldb_dn_new(talloc_tos(), ctx
->ldb
, dnstr
);
642 DBG_DEBUG("ldb_dn_new(%s) failed\n", dnstr
);
646 if (ctx
->deny_ous
!= NULL
) {
647 bool denied
= check_dn(ctx
->deny_ous
, dn
);
649 DBG_WARNING("Denied %s\n", dnstr
);
654 if (ctx
->allow_ous
== NULL
) {
656 * Only a few denied OUs around, allow by
663 if (ctx
->allow_ous
!= NULL
) {
664 bool allowed
= check_dn(ctx
->allow_ous
, dn
);
668 DBG_WARNING("Did not allow %s\n", dnstr
);
674 static NTSTATUS
idmap_ad_query_user(struct idmap_domain
*domain
,
675 struct wbint_userinfo
*info
)
677 struct idmap_ad_context
*ctx
;
680 char *sidstr
, *filter
;
681 const char *attrs
[4];
683 struct tldap_message
**msgs
;
685 status
= idmap_ad_get_context(domain
, &ctx
);
686 if (!NT_STATUS_IS_OK(status
)) {
690 if (!(ctx
->unix_primary_group
|| ctx
->unix_nss_info
)) {
694 attrs
[0] = ctx
->schema
->gid
;
695 attrs
[1] = ctx
->schema
->gecos
;
696 attrs
[2] = ctx
->schema
->dir
;
697 attrs
[3] = ctx
->schema
->shell
;
699 sidstr
= ldap_encode_ndr_dom_sid(talloc_tos(), &info
->user_sid
);
700 if (sidstr
== NULL
) {
701 return NT_STATUS_NO_MEMORY
;
704 filter
= talloc_asprintf(talloc_tos(), "(objectsid=%s)", sidstr
);
706 if (filter
== NULL
) {
707 return NT_STATUS_NO_MEMORY
;
710 DBG_DEBUG("Filter: [%s]\n", filter
);
712 rc
= tldap_search(ctx
->ld
, ctx
->default_nc
, TLDAP_SCOPE_SUB
, filter
,
713 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
714 0, 0, 0, talloc_tos(), &msgs
);
715 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
716 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
721 num_msgs
= talloc_array_length(msgs
);
723 for (i
=0; i
<num_msgs
; i
++) {
724 struct tldap_message
*msg
= msgs
[i
];
728 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
731 ok
= tldap_entry_dn(msg
, &dn
);
735 ok
= idmap_ad_dn_filter(domain
, dn
);
737 DBG_DEBUG("%s filtered out\n", dn
);
741 if (ctx
->unix_primary_group
) {
744 ok
= tldap_pull_uint32(msg
, ctx
->schema
->gid
, &gid
);
746 DBG_DEBUG("Setting primary group "
747 "to %"PRIu32
" from attr %s\n",
748 gid
, ctx
->schema
->gid
);
749 info
->primary_gid
= gid
;
753 if (ctx
->unix_nss_info
) {
756 attr
= tldap_talloc_single_attribute(
757 msg
, ctx
->schema
->dir
, talloc_tos());
759 info
->homedir
= talloc_move(info
, &attr
);
763 attr
= tldap_talloc_single_attribute(
764 msg
, ctx
->schema
->shell
, talloc_tos());
766 info
->shell
= talloc_move(info
, &attr
);
770 attr
= tldap_talloc_single_attribute(
771 msg
, ctx
->schema
->gecos
, talloc_tos());
773 info
->full_name
= talloc_move(info
, &attr
);
782 static NTSTATUS
idmap_ad_query_user_retry(struct idmap_domain
*domain
,
783 struct wbint_userinfo
*info
)
785 const NTSTATUS status_server_down
=
786 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN
));
789 status
= idmap_ad_query_user(domain
, info
);
791 if (NT_STATUS_EQUAL(status
, status_server_down
)) {
792 TALLOC_FREE(domain
->private_data
);
793 status
= idmap_ad_query_user(domain
, info
);
799 static NTSTATUS
idmap_ad_initialize(struct idmap_domain
*dom
)
801 dom
->query_user
= idmap_ad_query_user_retry
;
802 dom
->private_data
= NULL
;
806 static NTSTATUS
idmap_ad_get_context(struct idmap_domain
*dom
,
807 struct idmap_ad_context
**pctx
)
809 struct idmap_ad_context
*ctx
= NULL
;
814 * Make sure we never try to use LDAP against
815 * a trusted domain as AD_DC.
817 * This shouldn't be called currently,
818 * but you never know what happens in future.
820 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
823 if (dom
->private_data
!= NULL
) {
824 *pctx
= talloc_get_type_abort(dom
->private_data
,
825 struct idmap_ad_context
);
829 status
= idmap_ad_context_create(dom
, dom
, dom
->name
, &ctx
);
830 if (!NT_STATUS_IS_OK(status
)) {
831 DBG_DEBUG("idmap_ad_context_create failed: %s\n",
836 dom
->private_data
= ctx
;
841 static NTSTATUS
idmap_ad_unixids_to_sids(struct idmap_domain
*dom
,
844 struct idmap_ad_context
*ctx
;
847 struct tldap_message
**msgs
;
850 char *u_filter
, *g_filter
, *filter
;
852 const char *attrs
[] = {
855 NULL
, /* attr_uidnumber */
856 NULL
, /* attr_gidnumber */
859 status
= idmap_ad_get_context(dom
, &ctx
);
860 if (!NT_STATUS_IS_OK(status
)) {
864 attrs
[2] = ctx
->schema
->uid
;
865 attrs
[3] = ctx
->schema
->gid
;
867 u_filter
= talloc_strdup(talloc_tos(), "");
868 if (u_filter
== NULL
) {
869 return NT_STATUS_NO_MEMORY
;
872 g_filter
= talloc_strdup(talloc_tos(), "");
873 if (g_filter
== NULL
) {
874 return NT_STATUS_NO_MEMORY
;
877 for (i
=0; ids
[i
] != NULL
; i
++) {
878 struct id_map
*id
= ids
[i
];
880 id
->status
= ID_UNKNOWN
;
882 switch (id
->xid
.type
) {
884 u_filter
= talloc_asprintf_append_buffer(
885 u_filter
, "(%s=%ju)", ctx
->schema
->uid
,
886 (uintmax_t)id
->xid
.id
);
887 if (u_filter
== NULL
) {
888 return NT_STATUS_NO_MEMORY
;
894 g_filter
= talloc_asprintf_append_buffer(
895 g_filter
, "(%s=%ju)", ctx
->schema
->gid
,
896 (uintmax_t)id
->xid
.id
);
897 if (g_filter
== NULL
) {
898 return NT_STATUS_NO_MEMORY
;
904 DBG_WARNING("Unknown id type: %u\n",
905 (unsigned)id
->xid
.type
);
910 filter
= talloc_strdup(talloc_tos(), "(|");
911 if (filter
== NULL
) {
912 return NT_STATUS_NO_MEMORY
;
915 if (*u_filter
!= '\0') {
916 filter
= talloc_asprintf_append_buffer(
918 "(&(|(sAMAccountType=%d)(sAMAccountType=%d)"
919 "(sAMAccountType=%d))(|%s))",
920 ATYPE_NORMAL_ACCOUNT
, ATYPE_WORKSTATION_TRUST
,
921 ATYPE_INTERDOMAIN_TRUST
, u_filter
);
922 if (filter
== NULL
) {
923 return NT_STATUS_NO_MEMORY
;
926 TALLOC_FREE(u_filter
);
928 if (*g_filter
!= '\0') {
929 filter
= talloc_asprintf_append_buffer(
931 "(&(|(sAMAccountType=%d)(sAMAccountType=%d))(|%s))",
932 ATYPE_SECURITY_GLOBAL_GROUP
,
933 ATYPE_SECURITY_LOCAL_GROUP
,
935 if (filter
== NULL
) {
936 return NT_STATUS_NO_MEMORY
;
939 TALLOC_FREE(g_filter
);
941 filter
= talloc_asprintf_append_buffer(filter
, ")");
942 if (filter
== NULL
) {
943 return NT_STATUS_NO_MEMORY
;
946 DBG_DEBUG("Filter: [%s]\n", filter
);
948 rc
= tldap_search(ctx
->ld
, ctx
->default_nc
, TLDAP_SCOPE_SUB
, filter
,
949 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
950 0, 0, 0, talloc_tos(), &msgs
);
951 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
952 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
957 num_msgs
= talloc_array_length(msgs
);
959 for (i
=0; i
<num_msgs
; i
++) {
960 struct tldap_message
*msg
= msgs
[i
];
968 struct dom_sid_buf sidbuf
;
970 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
974 ok
= tldap_entry_dn(msg
, &dn
);
976 DBG_DEBUG("No dn found in msg %zu\n", i
);
980 ok
= idmap_ad_dn_filter(dom
, dn
);
982 DBG_DEBUG("%s filtered out\n", dn
);
986 ok
= tldap_pull_uint32(msg
, "sAMAccountType", &atype
);
988 DBG_DEBUG("No atype in object %s\n", dn
);
992 switch (atype
& 0xF0000000) {
993 case ATYPE_SECURITY_GLOBAL_GROUP
:
994 case ATYPE_SECURITY_LOCAL_GROUP
:
997 case ATYPE_NORMAL_ACCOUNT
:
998 case ATYPE_WORKSTATION_TRUST
:
999 case ATYPE_INTERDOMAIN_TRUST
:
1003 DBG_WARNING("unrecognized SAM account type %08x\n",
1008 ok
= tldap_pull_uint32(msg
, (type
== ID_TYPE_UID
) ?
1009 ctx
->schema
->uid
: ctx
->schema
->gid
,
1012 DBG_WARNING("No unix id in object %s\n", dn
);
1016 ok
= tldap_pull_binsid(msg
, "objectSid", &sid
);
1018 DBG_DEBUG("No objectSid in object %s\n", dn
);
1023 for (j
=0; ids
[j
]; j
++) {
1024 if ((type
== ids
[j
]->xid
.type
) &&
1025 (xid
== ids
[j
]->xid
.id
)) {
1031 DBG_DEBUG("Got unexpected sid %s from object %s\n",
1032 dom_sid_str_buf(&sid
, &sidbuf
),
1037 sid_copy(map
->sid
, &sid
);
1038 map
->status
= ID_MAPPED
;
1040 DBG_DEBUG("Mapped %s -> %ju (%d)\n",
1041 dom_sid_str_buf(map
->sid
, &sidbuf
),
1042 (uintmax_t)map
->xid
.id
, map
->xid
.type
);
1047 return NT_STATUS_OK
;
1050 static NTSTATUS
idmap_ad_sids_to_unixids(struct idmap_domain
*dom
,
1051 struct id_map
**ids
)
1053 struct idmap_ad_context
*ctx
;
1056 struct tldap_message
**msgs
;
1061 const char *attrs
[] = {
1064 NULL
, /* attr_uidnumber */
1065 NULL
, /* attr_gidnumber */
1068 status
= idmap_ad_get_context(dom
, &ctx
);
1069 if (!NT_STATUS_IS_OK(status
)) {
1073 attrs
[2] = ctx
->schema
->uid
;
1074 attrs
[3] = ctx
->schema
->gid
;
1076 filter
= talloc_asprintf(
1078 "(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)"
1079 "(sAMAccountType=%d)(sAMAccountType=%d))(|",
1080 ATYPE_NORMAL_ACCOUNT
, ATYPE_WORKSTATION_TRUST
,
1081 ATYPE_INTERDOMAIN_TRUST
, ATYPE_SECURITY_GLOBAL_GROUP
,
1082 ATYPE_SECURITY_LOCAL_GROUP
);
1083 if (filter
== NULL
) {
1084 return NT_STATUS_NO_MEMORY
;
1087 for (i
=0; ids
[i
]; i
++) {
1090 ids
[i
]->status
= ID_UNKNOWN
;
1092 sidstr
= ldap_encode_ndr_dom_sid(talloc_tos(), ids
[i
]->sid
);
1093 if (sidstr
== NULL
) {
1094 return NT_STATUS_NO_MEMORY
;
1097 filter
= talloc_asprintf_append_buffer(
1098 filter
, "(objectSid=%s)", sidstr
);
1099 TALLOC_FREE(sidstr
);
1100 if (filter
== NULL
) {
1101 return NT_STATUS_NO_MEMORY
;
1105 filter
= talloc_asprintf_append_buffer(filter
, "))");
1106 if (filter
== NULL
) {
1107 return NT_STATUS_NO_MEMORY
;
1110 DBG_DEBUG("Filter: [%s]\n", filter
);
1112 rc
= tldap_search(ctx
->ld
, ctx
->default_nc
, TLDAP_SCOPE_SUB
, filter
,
1113 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
1114 0, 0, 0, talloc_tos(), &msgs
);
1115 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
1116 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
1119 TALLOC_FREE(filter
);
1121 num_msgs
= talloc_array_length(msgs
);
1123 for (i
=0; i
<num_msgs
; i
++) {
1124 struct tldap_message
*msg
= msgs
[i
];
1130 uint64_t account_type
, xid
;
1132 struct dom_sid_buf buf
;
1134 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
1138 ok
= tldap_entry_dn(msg
, &dn
);
1140 DBG_DEBUG("No dn found in msg %zu\n", i
);
1144 ok
= idmap_ad_dn_filter(dom
, dn
);
1146 DBG_DEBUG("%s filtered out\n", dn
);
1150 ok
= tldap_pull_binsid(msg
, "objectSid", &sid
);
1152 DBG_DEBUG("No objectSid in object %s\n", dn
);
1157 for (j
=0; ids
[j
]; j
++) {
1158 if (dom_sid_equal(&sid
, ids
[j
]->sid
)) {
1164 DBG_DEBUG("Got unexpected sid %s from object %s\n",
1165 dom_sid_str_buf(&sid
, &buf
),
1170 ok
= tldap_pull_uint64(msg
, "sAMAccountType", &account_type
);
1172 DBG_DEBUG("No sAMAccountType in %s\n", dn
);
1176 switch (account_type
& 0xF0000000) {
1177 case ATYPE_SECURITY_GLOBAL_GROUP
:
1178 case ATYPE_SECURITY_LOCAL_GROUP
:
1181 case ATYPE_NORMAL_ACCOUNT
:
1182 case ATYPE_WORKSTATION_TRUST
:
1183 case ATYPE_INTERDOMAIN_TRUST
:
1187 DBG_WARNING("unrecognized SAM account type %"PRIu64
"\n",
1192 ok
= tldap_pull_uint64(msg
,
1193 type
== ID_TYPE_UID
?
1194 ctx
->schema
->uid
: ctx
->schema
->gid
,
1197 DBG_DEBUG("No xid in %s\n", dn
);
1202 map
->xid
.type
= type
;
1204 map
->status
= ID_MAPPED
;
1206 DEBUG(10, ("Mapped %s -> %lu (%d)\n",
1207 dom_sid_str_buf(map
->sid
, &buf
),
1208 (unsigned long)map
->xid
.id
, map
->xid
.type
));
1213 return NT_STATUS_OK
;
1216 static NTSTATUS
idmap_ad_unixids_to_sids_retry(struct idmap_domain
*dom
,
1217 struct id_map
**ids
)
1219 const NTSTATUS status_server_down
=
1220 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN
));
1223 status
= idmap_ad_unixids_to_sids(dom
, ids
);
1225 if (NT_STATUS_EQUAL(status
, status_server_down
)) {
1226 TALLOC_FREE(dom
->private_data
);
1227 status
= idmap_ad_unixids_to_sids(dom
, ids
);
1233 static NTSTATUS
idmap_ad_sids_to_unixids_retry(struct idmap_domain
*dom
,
1234 struct id_map
**ids
)
1236 const NTSTATUS status_server_down
=
1237 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN
));
1240 status
= idmap_ad_sids_to_unixids(dom
, ids
);
1242 if (NT_STATUS_EQUAL(status
, status_server_down
)) {
1243 TALLOC_FREE(dom
->private_data
);
1244 status
= idmap_ad_sids_to_unixids(dom
, ids
);
1250 static const struct idmap_methods ad_methods
= {
1251 .init
= idmap_ad_initialize
,
1252 .unixids_to_sids
= idmap_ad_unixids_to_sids_retry
,
1253 .sids_to_unixids
= idmap_ad_sids_to_unixids_retry
,
1257 NTSTATUS
idmap_ad_init(TALLOC_CTX
*ctx
)
1261 status
= smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION
,
1263 if (!NT_STATUS_IS_OK(status
)) {
1267 status
= idmap_ad_nss_init(ctx
);
1268 if (!NT_STATUS_IS_OK(status
)) {
1272 return NT_STATUS_OK
;