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"
24 #include "tldap_gensec_bind.h"
25 #include "tldap_util.h"
27 #include "lib/param/param.h"
28 #include "auth/gensec/gensec.h"
29 #include "librpc/gen_ndr/ndr_netlogon.h"
30 #include "libads/ldap_schema_oids.h"
31 #include "../libds/common/flags.h"
32 #include "libcli/ldap/ldap_ndr.h"
33 #include "libcli/security/dom_sid.h"
34 #include "source3/libads/sitename_cache.h"
35 #include "source3/libads/kerberos_proto.h"
36 #include "source3/librpc/gen_ndr/ads.h"
37 #include "source3/lib/global_contexts.h"
40 struct idmap_ad_schema_names
;
42 struct idmap_ad_context
{
43 struct idmap_domain
*dom
;
44 struct tldap_context
*ld
;
45 struct idmap_ad_schema_names
*schema
;
46 const char *default_nc
;
48 bool unix_primary_group
;
51 struct ldb_context
*ldb
;
52 struct ldb_dn
**deny_ous
;
53 struct ldb_dn
**allow_ous
;
56 static NTSTATUS
idmap_ad_get_context(struct idmap_domain
*dom
,
57 struct idmap_ad_context
**pctx
);
59 static char *get_schema_path(TALLOC_CTX
*mem_ctx
, struct tldap_context
*ld
)
61 struct tldap_message
*rootdse
;
63 rootdse
= tldap_rootdse(ld
);
64 if (rootdse
== NULL
) {
68 return tldap_talloc_single_attribute(rootdse
, "schemaNamingContext",
72 static char *get_default_nc(TALLOC_CTX
*mem_ctx
, struct tldap_context
*ld
)
74 struct tldap_message
*rootdse
;
76 rootdse
= tldap_rootdse(ld
);
77 if (rootdse
== NULL
) {
81 return tldap_talloc_single_attribute(rootdse
, "defaultNamingContext",
85 struct idmap_ad_schema_names
{
94 static TLDAPRC
get_attrnames_by_oids(struct tldap_context
*ld
,
96 const char *schema_path
,
102 const char *attrs
[] = { "lDAPDisplayName", "attributeId" };
105 struct tldap_message
**msgs
;
108 filter
= talloc_strdup(mem_ctx
, "(|");
110 for (i
=0; i
<num_oids
; i
++) {
111 talloc_asprintf_addbuf(&filter
, "(attributeId=%s)", oids
[i
]);
113 talloc_asprintf_addbuf(&filter
, ")");
115 if (filter
== NULL
) {
116 return TLDAP_NO_MEMORY
;
119 rc
= tldap_search(ld
, schema_path
, TLDAP_SCOPE_SUB
, filter
,
120 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
121 0, 0, 0, mem_ctx
, &msgs
);;
123 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
127 for (i
=0; i
<num_oids
; i
++) {
131 num_msgs
= talloc_array_length(msgs
);
133 for (i
=0; i
<num_msgs
; i
++) {
134 struct tldap_message
*msg
= msgs
[i
];
138 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
139 /* Could be a TLDAP_RES_SEARCH_REFERENCE */
143 oid
= tldap_talloc_single_attribute(
144 msg
, "attributeId", msg
);
149 for (j
=0; j
<num_oids
; j
++) {
150 if (strequal(oid
, oids
[j
])) {
161 names
[j
] = tldap_talloc_single_attribute(
162 msg
, "lDAPDisplayName", mem_ctx
);
166 for (i
=0; i
<num_oids
; i
++) {
167 if (names
[i
] == NULL
) {
168 DBG_ERR("Failed to retrieve schema name for "
169 "oid [%s]. Schema mode is incorrect "
170 "for this domain.\n", oids
[i
]);
171 return TLDAP_FILTER_ERROR
;
175 return TLDAP_SUCCESS
;
178 static TLDAPRC
get_posix_schema_names(struct tldap_context
*ld
,
179 const char *schema_mode
,
181 struct idmap_ad_schema_names
**pschema
)
184 struct idmap_ad_schema_names
*schema
;
186 const char *oids_sfu
[] = {
187 ADS_ATTR_SFU_UIDNUMBER_OID
,
188 ADS_ATTR_SFU_GIDNUMBER_OID
,
189 ADS_ATTR_SFU_HOMEDIR_OID
,
190 ADS_ATTR_SFU_SHELL_OID
,
191 ADS_ATTR_SFU_GECOS_OID
,
194 const char *oids_sfu20
[] = {
195 ADS_ATTR_SFU20_UIDNUMBER_OID
,
196 ADS_ATTR_SFU20_GIDNUMBER_OID
,
197 ADS_ATTR_SFU20_HOMEDIR_OID
,
198 ADS_ATTR_SFU20_SHELL_OID
,
199 ADS_ATTR_SFU20_GECOS_OID
,
200 ADS_ATTR_SFU20_UID_OID
202 const char *oids_rfc2307
[] = {
203 ADS_ATTR_RFC2307_UIDNUMBER_OID
,
204 ADS_ATTR_RFC2307_GIDNUMBER_OID
,
205 ADS_ATTR_RFC2307_HOMEDIR_OID
,
206 ADS_ATTR_RFC2307_SHELL_OID
,
207 ADS_ATTR_RFC2307_GECOS_OID
,
208 ADS_ATTR_RFC2307_UID_OID
214 schema
= talloc(mem_ctx
, struct idmap_ad_schema_names
);
215 if (schema
== NULL
) {
216 return TLDAP_NO_MEMORY
;
219 schema_path
= get_schema_path(schema
, ld
);
220 if (schema_path
== NULL
) {
222 return TLDAP_NO_MEMORY
;
227 if ((schema_mode
!= NULL
) && (schema_mode
[0] != '\0')) {
228 if (strequal(schema_mode
, "sfu")) {
230 } else if (strequal(schema_mode
, "sfu20")) {
232 } else if (strequal(schema_mode
, "rfc2307" )) {
235 DBG_WARNING("Unknown schema mode %s\n", schema_mode
);
239 rc
= get_attrnames_by_oids(ld
, schema
, schema_path
, 6, oids
, names
);
240 TALLOC_FREE(schema_path
);
241 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
246 schema
->uid
= names
[0];
247 schema
->gid
= names
[1];
248 schema
->dir
= names
[2];
249 schema
->shell
= names
[3];
250 schema
->gecos
= names
[4];
251 schema
->name
= names
[5];
255 return TLDAP_SUCCESS
;
258 static void PRINTF_ATTRIBUTE(3, 0) idmap_ad_tldap_debug(
260 enum tldap_debug_level level
,
264 int samba_level
= -1;
267 case TLDAP_DEBUG_FATAL
:
268 samba_level
= DBGLVL_ERR
;
270 case TLDAP_DEBUG_ERROR
:
271 samba_level
= DBGLVL_ERR
;
273 case TLDAP_DEBUG_WARNING
:
274 samba_level
= DBGLVL_WARNING
;
276 case TLDAP_DEBUG_TRACE
:
277 samba_level
= DBGLVL_DEBUG
;
281 if (CHECK_DEBUGLVL(samba_level
)) {
285 ret
= vasprintf(&s
, fmt
, ap
);
289 DEBUG(samba_level
, ("idmap_ad_tldap: %s", s
));
294 static uint32_t gensec_features_from_ldap_sasl_wrapping(void)
297 uint32_t gensec_features
= 0;
299 wrap_flags
= lp_client_ldap_sasl_wrapping();
300 if (wrap_flags
== -1) {
304 if (wrap_flags
& ADS_AUTH_SASL_SEAL
) {
305 gensec_features
|= GENSEC_FEATURE_SEAL
;
307 if (wrap_flags
& ADS_AUTH_SASL_SIGN
) {
308 gensec_features
|= GENSEC_FEATURE_SIGN
;
311 if (gensec_features
!= 0) {
312 gensec_features
|= GENSEC_FEATURE_LDAP_STYLE
;
315 return gensec_features
;
318 static NTSTATUS
idmap_ad_get_tldap_ctx(TALLOC_CTX
*mem_ctx
,
320 struct tldap_context
**pld
)
322 struct netr_DsRGetDCNameInfo
*dcinfo
;
323 struct sockaddr_storage dcaddr
;
324 struct cli_credentials
*creds
;
325 struct loadparm_context
*lp_ctx
;
326 struct tldap_context
*ld
;
327 uint32_t gensec_features
= gensec_features_from_ldap_sasl_wrapping();
328 char *sitename
= NULL
;
334 status
= wb_dsgetdcname_gencache_get(mem_ctx
, domname
, &dcinfo
);
335 if (!NT_STATUS_IS_OK(status
)) {
336 DBG_DEBUG("Could not get dcinfo for %s: %s\n", domname
,
341 if (dcinfo
->dc_unc
== NULL
) {
343 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
345 if (dcinfo
->dc_unc
[0] == '\\') {
348 if (dcinfo
->dc_unc
[0] == '\\') {
352 ok
= resolve_name(dcinfo
->dc_unc
, &dcaddr
, 0x20, true);
354 DBG_DEBUG("Could not resolve name %s\n", dcinfo
->dc_unc
);
356 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
359 sitename
= sitename_fetch(talloc_tos(), lp_realm());
362 * create_local_private_krb5_conf_for_domain() can deal with
366 ok
= create_local_private_krb5_conf_for_domain(
367 lp_realm(), lp_workgroup(), sitename
, &dcaddr
);
368 TALLOC_FREE(sitename
);
370 DBG_DEBUG("Could not create private krb5.conf\n");
372 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
375 status
= open_socket_out(&dcaddr
, 389, 10000, &fd
);
376 if (!NT_STATUS_IS_OK(status
)) {
377 DBG_DEBUG("open_socket_out failed: %s\n", nt_errstr(status
));
382 ld
= tldap_context_create(dcinfo
, fd
);
384 DBG_DEBUG("tldap_context_create failed\n");
387 return NT_STATUS_NO_MEMORY
;
389 tldap_set_debug(ld
, idmap_ad_tldap_debug
, NULL
);
392 * Here we use or own machine account as
393 * we run as domain member.
395 status
= pdb_get_trust_credentials(lp_workgroup(),
399 if (!NT_STATUS_IS_OK(status
)) {
400 DBG_DEBUG("pdb_get_trust_credentials() failed - %s\n",
406 lp_ctx
= loadparm_init_s3(dcinfo
, loadparm_s3_helpers());
407 if (lp_ctx
== NULL
) {
408 DBG_DEBUG("loadparm_init_s3 failed\n");
410 return NT_STATUS_NO_MEMORY
;
413 rc
= tldap_gensec_bind(ld
, creds
, "ldap", dcinfo
->dc_unc
, NULL
, lp_ctx
,
415 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
416 DBG_DEBUG("tldap_gensec_bind failed: %s\n",
417 tldap_errstr(dcinfo
, ld
, rc
));
419 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
422 rc
= tldap_fetch_rootdse(ld
);
423 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
424 DBG_DEBUG("tldap_fetch_rootdse failed: %s\n",
425 tldap_errstr(dcinfo
, ld
, rc
));
427 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
430 *pld
= talloc_move(mem_ctx
, &ld
);
435 static int idmap_ad_context_destructor(struct idmap_ad_context
*ctx
)
437 if ((ctx
->dom
!= NULL
) && (ctx
->dom
->private_data
== ctx
)) {
438 ctx
->dom
->private_data
= NULL
;
443 static struct ldb_dn
**str_list_to_dns(TALLOC_CTX
*mem_ctx
,
445 struct ldb_context
*ldb
,
446 const char **strlist
)
448 size_t i
, num_dns
= str_list_length(strlist
);
450 struct ldb_dn
**dns
= NULL
;
452 dns
= talloc_array(mem_ctx
, struct ldb_dn
*, num_dns
);
458 dbgstr
= talloc_strdup(talloc_tos(), "");
460 for (i
= 0; i
< num_dns
; i
++) {
461 dns
[i
] = ldb_dn_new(dns
, ldb
, strlist
[i
]);
462 if (dns
[i
] == NULL
) {
463 DBG_WARNING("ldb_dn_new(%s) failed\n", strlist
[i
]);
467 talloc_asprintf_addbuf(
470 ldb_dn_get_extended_linearized(dbgstr
, dns
[i
], 1));
473 DBG_DEBUG("%s %s\n", dbgmsg
, dbgstr
);
479 static NTSTATUS
idmap_ad_context_create(TALLOC_CTX
*mem_ctx
,
480 struct idmap_domain
*dom
,
482 struct idmap_ad_context
**pctx
)
484 struct idmap_ad_context
*ctx
;
485 const char *schema_mode
;
486 const char **allow
= NULL
;
487 const char **deny
= NULL
;
491 ctx
= talloc_zero(mem_ctx
, struct idmap_ad_context
);
493 return NT_STATUS_NO_MEMORY
;
497 talloc_set_destructor(ctx
, idmap_ad_context_destructor
);
499 status
= idmap_ad_get_tldap_ctx(ctx
, domname
, &ctx
->ld
);
500 if (!NT_STATUS_IS_OK(status
)) {
501 DBG_DEBUG("idmap_ad_get_tldap_ctx failed: %s\n",
507 ctx
->default_nc
= get_default_nc(ctx
, ctx
->ld
);
508 if (ctx
->default_nc
== NULL
) {
509 DBG_DEBUG("No default nc\n");
514 ctx
->unix_primary_group
= idmap_config_bool(
515 domname
, "unix_primary_group", false);
516 ctx
->unix_nss_info
= idmap_config_bool(
517 domname
, "unix_nss_info", false);
519 schema_mode
= idmap_config_const_string(
520 domname
, "schema_mode", "rfc2307");
522 rc
= get_posix_schema_names(ctx
->ld
, schema_mode
, ctx
, &ctx
->schema
);
523 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
524 DBG_DEBUG("get_posix_schema_names failed: %s\n",
525 tldap_errstr(ctx
, ctx
->ld
, rc
));
527 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
530 deny
= idmap_config_string_list(domname
, "deny ous", NULL
);
531 allow
= idmap_config_string_list(domname
, "allow ous", NULL
);
533 if ((deny
!= NULL
) || (allow
!= NULL
)) {
534 int ret
= ldb_global_init();
536 status
= map_nt_error_from_unix(errno
);
537 DBG_WARNING("ldb_global_init() failed: %s\n",
543 ctx
->ldb
= ldb_init(ctx
, global_event_context());
544 if (ctx
->ldb
== NULL
) {
545 status
= map_nt_error_from_unix(errno
);
546 DBG_WARNING("ldb_init() failed: %s\n", strerror(errno
));
553 ctx
->deny_ous
= str_list_to_dns(ctx
, "Denying", ctx
->ldb
, deny
);
554 if (ctx
->deny_ous
== NULL
) {
555 DBG_DEBUG("str_list_to_dns failed\n");
557 return NT_STATUS_NO_MEMORY
;
563 str_list_to_dns(ctx
, "Allowing", ctx
->ldb
, allow
);
564 if (ctx
->allow_ous
== NULL
) {
565 DBG_DEBUG("str_list_to_dns failed\n");
567 return NT_STATUS_NO_MEMORY
;
575 static bool check_dn(struct ldb_dn
**dns
, struct ldb_dn
*dn
)
577 size_t i
, num_dns
= talloc_array_length(dns
);
579 for (i
= 0; i
< num_dns
; i
++) {
580 struct ldb_dn
*base
= dns
[i
];
581 int ret
= ldb_dn_compare_base(base
, dn
);
589 static bool idmap_ad_dn_filter(struct idmap_domain
*dom
, const char *dnstr
)
591 struct idmap_ad_context
*ctx
= NULL
;
592 struct ldb_dn
*dn
= NULL
;
596 status
= idmap_ad_get_context(dom
, &ctx
);
597 if (!NT_STATUS_IS_OK(status
)) {
598 DBG_DEBUG("idmap_ad_get_context failed: %s\n",
603 if ((ctx
->allow_ous
== NULL
) && (ctx
->deny_ous
== NULL
)) {
610 dn
= ldb_dn_new(talloc_tos(), ctx
->ldb
, dnstr
);
612 DBG_DEBUG("ldb_dn_new(%s) failed\n", dnstr
);
616 if (ctx
->deny_ous
!= NULL
) {
617 bool denied
= check_dn(ctx
->deny_ous
, dn
);
619 DBG_WARNING("Denied %s\n", dnstr
);
624 if (ctx
->allow_ous
== NULL
) {
626 * Only a few denied OUs around, allow by
633 if (ctx
->allow_ous
!= NULL
) {
634 bool allowed
= check_dn(ctx
->allow_ous
, dn
);
638 DBG_WARNING("Did not allow %s\n", dnstr
);
644 static NTSTATUS
idmap_ad_query_user(struct idmap_domain
*domain
,
645 struct wbint_userinfo
*info
)
647 struct idmap_ad_context
*ctx
;
650 char *sidstr
, *filter
;
651 const char *attrs
[4];
653 struct tldap_message
**msgs
;
655 status
= idmap_ad_get_context(domain
, &ctx
);
656 if (!NT_STATUS_IS_OK(status
)) {
660 if (!(ctx
->unix_primary_group
|| ctx
->unix_nss_info
)) {
664 attrs
[0] = ctx
->schema
->gid
;
665 attrs
[1] = ctx
->schema
->gecos
;
666 attrs
[2] = ctx
->schema
->dir
;
667 attrs
[3] = ctx
->schema
->shell
;
669 sidstr
= ldap_encode_ndr_dom_sid(talloc_tos(), &info
->user_sid
);
670 if (sidstr
== NULL
) {
671 return NT_STATUS_NO_MEMORY
;
674 filter
= talloc_asprintf(talloc_tos(), "(objectsid=%s)", sidstr
);
676 if (filter
== NULL
) {
677 return NT_STATUS_NO_MEMORY
;
680 DBG_DEBUG("Filter: [%s]\n", filter
);
682 rc
= tldap_search(ctx
->ld
, ctx
->default_nc
, TLDAP_SCOPE_SUB
, filter
,
683 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
684 0, 0, 0, talloc_tos(), &msgs
);
685 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
686 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
691 num_msgs
= talloc_array_length(msgs
);
693 for (i
=0; i
<num_msgs
; i
++) {
694 struct tldap_message
*msg
= msgs
[i
];
698 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
701 ok
= tldap_entry_dn(msg
, &dn
);
705 ok
= idmap_ad_dn_filter(domain
, dn
);
707 DBG_DEBUG("%s filtered out\n", dn
);
711 if (ctx
->unix_primary_group
) {
714 ok
= tldap_pull_uint32(msg
, ctx
->schema
->gid
, &gid
);
716 DBG_DEBUG("Setting primary group "
717 "to %"PRIu32
" from attr %s\n",
718 gid
, ctx
->schema
->gid
);
719 info
->primary_gid
= gid
;
723 if (ctx
->unix_nss_info
) {
726 attr
= tldap_talloc_single_attribute(
727 msg
, ctx
->schema
->dir
, talloc_tos());
729 info
->homedir
= talloc_move(info
, &attr
);
733 attr
= tldap_talloc_single_attribute(
734 msg
, ctx
->schema
->shell
, talloc_tos());
736 info
->shell
= talloc_move(info
, &attr
);
740 attr
= tldap_talloc_single_attribute(
741 msg
, ctx
->schema
->gecos
, talloc_tos());
743 info
->full_name
= talloc_move(info
, &attr
);
752 static NTSTATUS
idmap_ad_query_user_retry(struct idmap_domain
*domain
,
753 struct wbint_userinfo
*info
)
755 const NTSTATUS status_server_down
=
756 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN
));
759 status
= idmap_ad_query_user(domain
, info
);
761 if (NT_STATUS_EQUAL(status
, status_server_down
)) {
762 TALLOC_FREE(domain
->private_data
);
763 status
= idmap_ad_query_user(domain
, info
);
769 static NTSTATUS
idmap_ad_initialize(struct idmap_domain
*dom
)
771 dom
->query_user
= idmap_ad_query_user_retry
;
772 dom
->private_data
= NULL
;
776 static NTSTATUS
idmap_ad_get_context(struct idmap_domain
*dom
,
777 struct idmap_ad_context
**pctx
)
779 struct idmap_ad_context
*ctx
= NULL
;
784 * Make sure we never try to use LDAP against
785 * a trusted domain as AD_DC.
787 * This shouldn't be called currently,
788 * but you never know what happens in future.
790 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
793 if (dom
->private_data
!= NULL
) {
794 *pctx
= talloc_get_type_abort(dom
->private_data
,
795 struct idmap_ad_context
);
799 status
= idmap_ad_context_create(dom
, dom
, dom
->name
, &ctx
);
800 if (!NT_STATUS_IS_OK(status
)) {
801 DBG_DEBUG("idmap_ad_context_create failed: %s\n",
806 dom
->private_data
= ctx
;
811 static NTSTATUS
idmap_ad_unixids_to_sids(struct idmap_domain
*dom
,
814 struct idmap_ad_context
*ctx
;
817 struct tldap_message
**msgs
;
820 char *u_filter
, *g_filter
, *filter
;
822 const char *attrs
[] = {
825 NULL
, /* attr_uidnumber */
826 NULL
, /* attr_gidnumber */
829 status
= idmap_ad_get_context(dom
, &ctx
);
830 if (!NT_STATUS_IS_OK(status
)) {
834 attrs
[2] = ctx
->schema
->uid
;
835 attrs
[3] = ctx
->schema
->gid
;
837 u_filter
= talloc_strdup(talloc_tos(), "");
838 if (u_filter
== NULL
) {
839 return NT_STATUS_NO_MEMORY
;
842 g_filter
= talloc_strdup(talloc_tos(), "");
843 if (g_filter
== NULL
) {
844 return NT_STATUS_NO_MEMORY
;
847 for (i
=0; ids
[i
] != NULL
; i
++) {
848 struct id_map
*id
= ids
[i
];
850 id
->status
= ID_UNKNOWN
;
852 switch (id
->xid
.type
) {
854 u_filter
= talloc_asprintf_append_buffer(
855 u_filter
, "(%s=%ju)", ctx
->schema
->uid
,
856 (uintmax_t)id
->xid
.id
);
857 if (u_filter
== NULL
) {
858 return NT_STATUS_NO_MEMORY
;
864 g_filter
= talloc_asprintf_append_buffer(
865 g_filter
, "(%s=%ju)", ctx
->schema
->gid
,
866 (uintmax_t)id
->xid
.id
);
867 if (g_filter
== NULL
) {
868 return NT_STATUS_NO_MEMORY
;
874 DBG_WARNING("Unknown id type: %u\n",
875 (unsigned)id
->xid
.type
);
880 filter
= talloc_strdup(talloc_tos(), "(|");
881 if (filter
== NULL
) {
882 return NT_STATUS_NO_MEMORY
;
885 if (*u_filter
!= '\0') {
886 filter
= talloc_asprintf_append_buffer(
888 "(&(|(sAMAccountType=%d)(sAMAccountType=%d)"
889 "(sAMAccountType=%d))(|%s))",
890 ATYPE_NORMAL_ACCOUNT
, ATYPE_WORKSTATION_TRUST
,
891 ATYPE_INTERDOMAIN_TRUST
, u_filter
);
892 if (filter
== NULL
) {
893 return NT_STATUS_NO_MEMORY
;
896 TALLOC_FREE(u_filter
);
898 if (*g_filter
!= '\0') {
899 filter
= talloc_asprintf_append_buffer(
901 "(&(|(sAMAccountType=%d)(sAMAccountType=%d))(|%s))",
902 ATYPE_SECURITY_GLOBAL_GROUP
,
903 ATYPE_SECURITY_LOCAL_GROUP
,
905 if (filter
== NULL
) {
906 return NT_STATUS_NO_MEMORY
;
909 TALLOC_FREE(g_filter
);
911 filter
= talloc_asprintf_append_buffer(filter
, ")");
912 if (filter
== NULL
) {
913 return NT_STATUS_NO_MEMORY
;
916 DBG_DEBUG("Filter: [%s]\n", filter
);
918 rc
= tldap_search(ctx
->ld
, ctx
->default_nc
, TLDAP_SCOPE_SUB
, filter
,
919 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
920 0, 0, 0, talloc_tos(), &msgs
);
921 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
922 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
927 num_msgs
= talloc_array_length(msgs
);
929 for (i
=0; i
<num_msgs
; i
++) {
930 struct tldap_message
*msg
= msgs
[i
];
938 struct dom_sid_buf sidbuf
;
940 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
944 ok
= tldap_entry_dn(msg
, &dn
);
946 DBG_DEBUG("No dn found in msg %zu\n", i
);
950 ok
= idmap_ad_dn_filter(dom
, dn
);
952 DBG_DEBUG("%s filtered out\n", dn
);
956 ok
= tldap_pull_uint32(msg
, "sAMAccountType", &atype
);
958 DBG_DEBUG("No atype in object %s\n", dn
);
962 switch (atype
& 0xF0000000) {
963 case ATYPE_SECURITY_GLOBAL_GROUP
:
964 case ATYPE_SECURITY_LOCAL_GROUP
:
967 case ATYPE_NORMAL_ACCOUNT
:
968 case ATYPE_WORKSTATION_TRUST
:
969 case ATYPE_INTERDOMAIN_TRUST
:
973 DBG_WARNING("unrecognized SAM account type %08x\n",
978 ok
= tldap_pull_uint32(msg
, (type
== ID_TYPE_UID
) ?
979 ctx
->schema
->uid
: ctx
->schema
->gid
,
982 DBG_WARNING("No unix id in object %s\n", dn
);
986 ok
= tldap_pull_binsid(msg
, "objectSid", &sid
);
988 DBG_DEBUG("No objectSid in object %s\n", dn
);
993 for (j
=0; ids
[j
]; j
++) {
994 if ((type
== ids
[j
]->xid
.type
) &&
995 (xid
== ids
[j
]->xid
.id
)) {
1001 DBG_DEBUG("Got unexpected sid %s from object %s\n",
1002 dom_sid_str_buf(&sid
, &sidbuf
),
1007 sid_copy(map
->sid
, &sid
);
1008 map
->status
= ID_MAPPED
;
1010 DBG_DEBUG("Mapped %s -> %ju (%d)\n",
1011 dom_sid_str_buf(map
->sid
, &sidbuf
),
1012 (uintmax_t)map
->xid
.id
, map
->xid
.type
);
1017 return NT_STATUS_OK
;
1020 static NTSTATUS
idmap_ad_sids_to_unixids(struct idmap_domain
*dom
,
1021 struct id_map
**ids
)
1023 struct idmap_ad_context
*ctx
;
1026 struct tldap_message
**msgs
;
1031 const char *attrs
[] = {
1034 NULL
, /* attr_uidnumber */
1035 NULL
, /* attr_gidnumber */
1038 status
= idmap_ad_get_context(dom
, &ctx
);
1039 if (!NT_STATUS_IS_OK(status
)) {
1043 attrs
[2] = ctx
->schema
->uid
;
1044 attrs
[3] = ctx
->schema
->gid
;
1046 filter
= talloc_asprintf(
1048 "(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)"
1049 "(sAMAccountType=%d)(sAMAccountType=%d))(|",
1050 ATYPE_NORMAL_ACCOUNT
, ATYPE_WORKSTATION_TRUST
,
1051 ATYPE_INTERDOMAIN_TRUST
, ATYPE_SECURITY_GLOBAL_GROUP
,
1052 ATYPE_SECURITY_LOCAL_GROUP
);
1053 if (filter
== NULL
) {
1054 return NT_STATUS_NO_MEMORY
;
1057 for (i
=0; ids
[i
]; i
++) {
1060 ids
[i
]->status
= ID_UNKNOWN
;
1062 sidstr
= ldap_encode_ndr_dom_sid(talloc_tos(), ids
[i
]->sid
);
1063 if (sidstr
== NULL
) {
1064 return NT_STATUS_NO_MEMORY
;
1067 filter
= talloc_asprintf_append_buffer(
1068 filter
, "(objectSid=%s)", sidstr
);
1069 TALLOC_FREE(sidstr
);
1070 if (filter
== NULL
) {
1071 return NT_STATUS_NO_MEMORY
;
1075 filter
= talloc_asprintf_append_buffer(filter
, "))");
1076 if (filter
== NULL
) {
1077 return NT_STATUS_NO_MEMORY
;
1080 DBG_DEBUG("Filter: [%s]\n", filter
);
1082 rc
= tldap_search(ctx
->ld
, ctx
->default_nc
, TLDAP_SCOPE_SUB
, filter
,
1083 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
1084 0, 0, 0, talloc_tos(), &msgs
);
1085 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
1086 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
1089 TALLOC_FREE(filter
);
1091 num_msgs
= talloc_array_length(msgs
);
1093 for (i
=0; i
<num_msgs
; i
++) {
1094 struct tldap_message
*msg
= msgs
[i
];
1100 uint64_t account_type
, xid
;
1102 struct dom_sid_buf buf
;
1104 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
1108 ok
= tldap_entry_dn(msg
, &dn
);
1110 DBG_DEBUG("No dn found in msg %zu\n", i
);
1114 ok
= idmap_ad_dn_filter(dom
, dn
);
1116 DBG_DEBUG("%s filtered out\n", dn
);
1120 ok
= tldap_pull_binsid(msg
, "objectSid", &sid
);
1122 DBG_DEBUG("No objectSid in object %s\n", dn
);
1127 for (j
=0; ids
[j
]; j
++) {
1128 if (dom_sid_equal(&sid
, ids
[j
]->sid
)) {
1134 DBG_DEBUG("Got unexpected sid %s from object %s\n",
1135 dom_sid_str_buf(&sid
, &buf
),
1140 ok
= tldap_pull_uint64(msg
, "sAMAccountType", &account_type
);
1142 DBG_DEBUG("No sAMAccountType in %s\n", dn
);
1146 switch (account_type
& 0xF0000000) {
1147 case ATYPE_SECURITY_GLOBAL_GROUP
:
1148 case ATYPE_SECURITY_LOCAL_GROUP
:
1151 case ATYPE_NORMAL_ACCOUNT
:
1152 case ATYPE_WORKSTATION_TRUST
:
1153 case ATYPE_INTERDOMAIN_TRUST
:
1157 DBG_WARNING("unrecognized SAM account type %"PRIu64
"\n",
1162 ok
= tldap_pull_uint64(msg
,
1163 type
== ID_TYPE_UID
?
1164 ctx
->schema
->uid
: ctx
->schema
->gid
,
1167 DBG_DEBUG("No xid in %s\n", dn
);
1172 map
->xid
.type
= type
;
1174 map
->status
= ID_MAPPED
;
1176 DEBUG(10, ("Mapped %s -> %lu (%d)\n",
1177 dom_sid_str_buf(map
->sid
, &buf
),
1178 (unsigned long)map
->xid
.id
, map
->xid
.type
));
1183 return NT_STATUS_OK
;
1186 static NTSTATUS
idmap_ad_unixids_to_sids_retry(struct idmap_domain
*dom
,
1187 struct id_map
**ids
)
1189 const NTSTATUS status_server_down
=
1190 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN
));
1193 status
= idmap_ad_unixids_to_sids(dom
, ids
);
1195 if (NT_STATUS_EQUAL(status
, status_server_down
)) {
1196 TALLOC_FREE(dom
->private_data
);
1197 status
= idmap_ad_unixids_to_sids(dom
, ids
);
1203 static NTSTATUS
idmap_ad_sids_to_unixids_retry(struct idmap_domain
*dom
,
1204 struct id_map
**ids
)
1206 const NTSTATUS status_server_down
=
1207 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN
));
1210 status
= idmap_ad_sids_to_unixids(dom
, ids
);
1212 if (NT_STATUS_EQUAL(status
, status_server_down
)) {
1213 TALLOC_FREE(dom
->private_data
);
1214 status
= idmap_ad_sids_to_unixids(dom
, ids
);
1220 static const struct idmap_methods ad_methods
= {
1221 .init
= idmap_ad_initialize
,
1222 .unixids_to_sids
= idmap_ad_unixids_to_sids_retry
,
1223 .sids_to_unixids
= idmap_ad_sids_to_unixids_retry
,
1227 NTSTATUS
idmap_ad_init(TALLOC_CTX
*ctx
)
1231 status
= smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION
,
1233 if (!NT_STATUS_IS_OK(status
)) {
1237 status
= idmap_ad_nss_init(ctx
);
1238 if (!NT_STATUS_IS_OK(status
)) {
1242 return NT_STATUS_OK
;