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 struct winbindd_domain
*creds_domain
= NULL
;
303 struct cli_credentials
*creds
;
304 struct loadparm_context
*lp_ctx
;
305 struct tldap_context
*ld
;
307 bool use_tls
= false;
308 bool use_starttls
= false;
310 uint32_t gensec_features
= 0;
311 char *sitename
= NULL
;
317 wrap_flags
= lp_client_ldap_sasl_wrapping();
319 if (wrap_flags
& ADS_AUTH_SASL_LDAPS
) {
322 } else if (wrap_flags
& ADS_AUTH_SASL_STARTTLS
) {
326 if (wrap_flags
& ADS_AUTH_SASL_SEAL
) {
327 gensec_features
|= GENSEC_FEATURE_SEAL
;
329 if (wrap_flags
& ADS_AUTH_SASL_SIGN
) {
330 gensec_features
|= GENSEC_FEATURE_SIGN
;
333 if (gensec_features
!= 0) {
334 gensec_features
|= GENSEC_FEATURE_LDAP_STYLE
;
337 status
= wb_dsgetdcname_gencache_get(mem_ctx
, domname
, &dcinfo
);
338 if (!NT_STATUS_IS_OK(status
)) {
339 DBG_DEBUG("Could not get dcinfo for %s: %s\n", domname
,
344 if (dcinfo
->dc_unc
== NULL
) {
346 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
348 if (dcinfo
->dc_unc
[0] == '\\') {
351 if (dcinfo
->dc_unc
[0] == '\\') {
355 ok
= resolve_name(dcinfo
->dc_unc
, &dcaddr
, 0x20, true);
357 DBG_DEBUG("Could not resolve name %s\n", dcinfo
->dc_unc
);
359 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
362 sitename
= sitename_fetch(talloc_tos(), lp_realm());
365 * create_local_private_krb5_conf_for_domain() can deal with
369 ok
= create_local_private_krb5_conf_for_domain(
370 lp_realm(), lp_workgroup(), sitename
, &dcaddr
);
371 TALLOC_FREE(sitename
);
373 DBG_DEBUG("Could not create private krb5.conf\n");
375 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
378 status
= open_socket_out(&dcaddr
, tcp_port
, 10000, &fd
);
379 if (!NT_STATUS_IS_OK(status
)) {
380 DBG_DEBUG("open_socket_out failed: %s\n", nt_errstr(status
));
385 ld
= tldap_context_create(dcinfo
, fd
);
387 DBG_DEBUG("tldap_context_create failed\n");
390 return NT_STATUS_NO_MEMORY
;
392 tldap_set_debug(ld
, idmap_ad_tldap_debug
, NULL
);
395 * Here we use or own machine account as
396 * we run as domain member.
398 creds_domain
= find_our_domain();
399 if (creds_domain
== NULL
) {
400 DBG_ERR("find_our_domain() returned NULL\n");
402 return NT_STATUS_INTERNAL_ERROR
;
404 status
= winbindd_get_trust_credentials(creds_domain
,
406 false, /* netlogon */
407 false, /* ipc_fallback */
409 if (!NT_STATUS_IS_OK(status
)) {
410 DBG_ERR("winbindd_get_trust_credentials(%s) failed - %s\n",
411 creds_domain
->name
, nt_errstr(status
));
416 lp_ctx
= loadparm_init_s3(dcinfo
, loadparm_s3_helpers());
417 if (lp_ctx
== NULL
) {
418 DBG_DEBUG("loadparm_init_s3 failed\n");
420 return NT_STATUS_NO_MEMORY
;
423 if (use_tls
&& !tldap_has_tls_tstream(ld
)) {
424 tldap_set_starttls_needed(ld
, use_starttls
);
426 rc
= tldap_tls_connect(ld
, lp_ctx
, dcinfo
->dc_unc
);
427 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
428 DBG_ERR("tldap_gensec_bind(%s) failed: %s\n",
430 tldap_errstr(dcinfo
, ld
, rc
));
432 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
436 rc
= tldap_gensec_bind(ld
, creds
, "ldap", dcinfo
->dc_unc
, NULL
, lp_ctx
,
438 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
439 DBG_DEBUG("tldap_gensec_bind failed: %s\n",
440 tldap_errstr(dcinfo
, ld
, rc
));
442 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
445 rc
= tldap_fetch_rootdse(ld
);
446 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
447 DBG_DEBUG("tldap_fetch_rootdse failed: %s\n",
448 tldap_errstr(dcinfo
, ld
, rc
));
450 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
453 *pld
= talloc_move(mem_ctx
, &ld
);
458 static int idmap_ad_context_destructor(struct idmap_ad_context
*ctx
)
460 if ((ctx
->dom
!= NULL
) && (ctx
->dom
->private_data
== ctx
)) {
461 ctx
->dom
->private_data
= NULL
;
466 static struct ldb_dn
**str_list_to_dns(TALLOC_CTX
*mem_ctx
,
468 struct ldb_context
*ldb
,
469 const char **strlist
)
471 size_t i
, num_dns
= str_list_length(strlist
);
473 struct ldb_dn
**dns
= NULL
;
475 dns
= talloc_array(mem_ctx
, struct ldb_dn
*, num_dns
);
481 dbgstr
= talloc_strdup(talloc_tos(), "");
483 for (i
= 0; i
< num_dns
; i
++) {
484 dns
[i
] = ldb_dn_new(dns
, ldb
, strlist
[i
]);
485 if (dns
[i
] == NULL
) {
486 DBG_WARNING("ldb_dn_new(%s) failed\n", strlist
[i
]);
490 talloc_asprintf_addbuf(
493 ldb_dn_get_extended_linearized(dbgstr
, dns
[i
], 1));
496 DBG_DEBUG("%s %s\n", dbgmsg
, dbgstr
);
502 static NTSTATUS
idmap_ad_context_create(TALLOC_CTX
*mem_ctx
,
503 struct idmap_domain
*dom
,
505 struct idmap_ad_context
**pctx
)
507 struct idmap_ad_context
*ctx
;
508 const char *schema_mode
;
509 const char **allow
= NULL
;
510 const char **deny
= NULL
;
514 ctx
= talloc_zero(mem_ctx
, struct idmap_ad_context
);
516 return NT_STATUS_NO_MEMORY
;
520 talloc_set_destructor(ctx
, idmap_ad_context_destructor
);
522 status
= idmap_ad_get_tldap_ctx(ctx
, domname
, &ctx
->ld
);
523 if (!NT_STATUS_IS_OK(status
)) {
524 DBG_DEBUG("idmap_ad_get_tldap_ctx failed: %s\n",
530 ctx
->default_nc
= get_default_nc(ctx
, ctx
->ld
);
531 if (ctx
->default_nc
== NULL
) {
532 DBG_DEBUG("No default nc\n");
537 ctx
->unix_primary_group
= idmap_config_bool(
538 domname
, "unix_primary_group", false);
539 ctx
->unix_nss_info
= idmap_config_bool(
540 domname
, "unix_nss_info", false);
542 schema_mode
= idmap_config_const_string(
543 domname
, "schema_mode", "rfc2307");
545 rc
= get_posix_schema_names(ctx
->ld
, schema_mode
, ctx
, &ctx
->schema
);
546 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
547 DBG_DEBUG("get_posix_schema_names failed: %s\n",
548 tldap_errstr(ctx
, ctx
->ld
, rc
));
550 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
553 deny
= idmap_config_string_list(domname
, "deny ous", NULL
);
554 allow
= idmap_config_string_list(domname
, "allow ous", NULL
);
556 if ((deny
!= NULL
) || (allow
!= NULL
)) {
557 int ret
= ldb_global_init();
559 status
= map_nt_error_from_unix(errno
);
560 DBG_WARNING("ldb_global_init() failed: %s\n",
566 ctx
->ldb
= ldb_init(ctx
, global_event_context());
567 if (ctx
->ldb
== NULL
) {
568 status
= map_nt_error_from_unix(errno
);
569 DBG_WARNING("ldb_init() failed: %s\n", strerror(errno
));
576 ctx
->deny_ous
= str_list_to_dns(ctx
, "Denying", ctx
->ldb
, deny
);
577 if (ctx
->deny_ous
== NULL
) {
578 DBG_DEBUG("str_list_to_dns failed\n");
580 return NT_STATUS_NO_MEMORY
;
586 str_list_to_dns(ctx
, "Allowing", ctx
->ldb
, allow
);
587 if (ctx
->allow_ous
== NULL
) {
588 DBG_DEBUG("str_list_to_dns failed\n");
590 return NT_STATUS_NO_MEMORY
;
598 static bool check_dn(struct ldb_dn
**dns
, struct ldb_dn
*dn
)
600 size_t i
, num_dns
= talloc_array_length(dns
);
602 for (i
= 0; i
< num_dns
; i
++) {
603 struct ldb_dn
*base
= dns
[i
];
604 int ret
= ldb_dn_compare_base(base
, dn
);
612 static bool idmap_ad_dn_filter(struct idmap_domain
*dom
, const char *dnstr
)
614 struct idmap_ad_context
*ctx
= NULL
;
615 struct ldb_dn
*dn
= NULL
;
619 status
= idmap_ad_get_context(dom
, &ctx
);
620 if (!NT_STATUS_IS_OK(status
)) {
621 DBG_DEBUG("idmap_ad_get_context failed: %s\n",
626 if ((ctx
->allow_ous
== NULL
) && (ctx
->deny_ous
== NULL
)) {
633 dn
= ldb_dn_new(talloc_tos(), ctx
->ldb
, dnstr
);
635 DBG_DEBUG("ldb_dn_new(%s) failed\n", dnstr
);
639 if (ctx
->deny_ous
!= NULL
) {
640 bool denied
= check_dn(ctx
->deny_ous
, dn
);
642 DBG_WARNING("Denied %s\n", dnstr
);
647 if (ctx
->allow_ous
== NULL
) {
649 * Only a few denied OUs around, allow by
656 if (ctx
->allow_ous
!= NULL
) {
657 bool allowed
= check_dn(ctx
->allow_ous
, dn
);
661 DBG_WARNING("Did not allow %s\n", dnstr
);
667 static NTSTATUS
idmap_ad_query_user(struct idmap_domain
*domain
,
668 struct wbint_userinfo
*info
)
670 struct idmap_ad_context
*ctx
;
673 char *sidstr
, *filter
;
674 const char *attrs
[4];
676 struct tldap_message
**msgs
;
678 status
= idmap_ad_get_context(domain
, &ctx
);
679 if (!NT_STATUS_IS_OK(status
)) {
683 if (!(ctx
->unix_primary_group
|| ctx
->unix_nss_info
)) {
687 attrs
[0] = ctx
->schema
->gid
;
688 attrs
[1] = ctx
->schema
->gecos
;
689 attrs
[2] = ctx
->schema
->dir
;
690 attrs
[3] = ctx
->schema
->shell
;
692 sidstr
= ldap_encode_ndr_dom_sid(talloc_tos(), &info
->user_sid
);
693 if (sidstr
== NULL
) {
694 return NT_STATUS_NO_MEMORY
;
697 filter
= talloc_asprintf(talloc_tos(), "(objectsid=%s)", sidstr
);
699 if (filter
== NULL
) {
700 return NT_STATUS_NO_MEMORY
;
703 DBG_DEBUG("Filter: [%s]\n", filter
);
705 rc
= tldap_search(ctx
->ld
, ctx
->default_nc
, TLDAP_SCOPE_SUB
, filter
,
706 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
707 0, 0, 0, talloc_tos(), &msgs
);
708 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
709 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
714 num_msgs
= talloc_array_length(msgs
);
716 for (i
=0; i
<num_msgs
; i
++) {
717 struct tldap_message
*msg
= msgs
[i
];
721 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
724 ok
= tldap_entry_dn(msg
, &dn
);
728 ok
= idmap_ad_dn_filter(domain
, dn
);
730 DBG_DEBUG("%s filtered out\n", dn
);
734 if (ctx
->unix_primary_group
) {
737 ok
= tldap_pull_uint32(msg
, ctx
->schema
->gid
, &gid
);
739 DBG_DEBUG("Setting primary group "
740 "to %"PRIu32
" from attr %s\n",
741 gid
, ctx
->schema
->gid
);
742 info
->primary_gid
= gid
;
746 if (ctx
->unix_nss_info
) {
749 attr
= tldap_talloc_single_attribute(
750 msg
, ctx
->schema
->dir
, talloc_tos());
752 info
->homedir
= talloc_move(info
, &attr
);
756 attr
= tldap_talloc_single_attribute(
757 msg
, ctx
->schema
->shell
, talloc_tos());
759 info
->shell
= talloc_move(info
, &attr
);
763 attr
= tldap_talloc_single_attribute(
764 msg
, ctx
->schema
->gecos
, talloc_tos());
766 info
->full_name
= talloc_move(info
, &attr
);
775 static NTSTATUS
idmap_ad_query_user_retry(struct idmap_domain
*domain
,
776 struct wbint_userinfo
*info
)
778 const NTSTATUS status_server_down
=
779 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN
));
782 status
= idmap_ad_query_user(domain
, info
);
784 if (NT_STATUS_EQUAL(status
, status_server_down
)) {
785 TALLOC_FREE(domain
->private_data
);
786 status
= idmap_ad_query_user(domain
, info
);
792 static NTSTATUS
idmap_ad_initialize(struct idmap_domain
*dom
)
794 dom
->query_user
= idmap_ad_query_user_retry
;
795 dom
->private_data
= NULL
;
799 static NTSTATUS
idmap_ad_get_context(struct idmap_domain
*dom
,
800 struct idmap_ad_context
**pctx
)
802 struct idmap_ad_context
*ctx
= NULL
;
807 * Make sure we never try to use LDAP against
808 * a trusted domain as AD_DC.
810 * This shouldn't be called currently,
811 * but you never know what happens in future.
813 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
816 if (dom
->private_data
!= NULL
) {
817 *pctx
= talloc_get_type_abort(dom
->private_data
,
818 struct idmap_ad_context
);
822 status
= idmap_ad_context_create(dom
, dom
, dom
->name
, &ctx
);
823 if (!NT_STATUS_IS_OK(status
)) {
824 DBG_DEBUG("idmap_ad_context_create failed: %s\n",
829 dom
->private_data
= ctx
;
834 static NTSTATUS
idmap_ad_unixids_to_sids(struct idmap_domain
*dom
,
837 struct idmap_ad_context
*ctx
;
840 struct tldap_message
**msgs
;
843 char *u_filter
, *g_filter
, *filter
;
845 const char *attrs
[] = {
848 NULL
, /* attr_uidnumber */
849 NULL
, /* attr_gidnumber */
852 status
= idmap_ad_get_context(dom
, &ctx
);
853 if (!NT_STATUS_IS_OK(status
)) {
857 attrs
[2] = ctx
->schema
->uid
;
858 attrs
[3] = ctx
->schema
->gid
;
860 u_filter
= talloc_strdup(talloc_tos(), "");
861 if (u_filter
== NULL
) {
862 return NT_STATUS_NO_MEMORY
;
865 g_filter
= talloc_strdup(talloc_tos(), "");
866 if (g_filter
== NULL
) {
867 return NT_STATUS_NO_MEMORY
;
870 for (i
=0; ids
[i
] != NULL
; i
++) {
871 struct id_map
*id
= ids
[i
];
873 id
->status
= ID_UNKNOWN
;
875 switch (id
->xid
.type
) {
877 u_filter
= talloc_asprintf_append_buffer(
878 u_filter
, "(%s=%ju)", ctx
->schema
->uid
,
879 (uintmax_t)id
->xid
.id
);
880 if (u_filter
== NULL
) {
881 return NT_STATUS_NO_MEMORY
;
887 g_filter
= talloc_asprintf_append_buffer(
888 g_filter
, "(%s=%ju)", ctx
->schema
->gid
,
889 (uintmax_t)id
->xid
.id
);
890 if (g_filter
== NULL
) {
891 return NT_STATUS_NO_MEMORY
;
897 DBG_WARNING("Unknown id type: %u\n",
898 (unsigned)id
->xid
.type
);
903 filter
= talloc_strdup(talloc_tos(), "(|");
904 if (filter
== NULL
) {
905 return NT_STATUS_NO_MEMORY
;
908 if (*u_filter
!= '\0') {
909 filter
= talloc_asprintf_append_buffer(
911 "(&(|(sAMAccountType=%d)(sAMAccountType=%d)"
912 "(sAMAccountType=%d))(|%s))",
913 ATYPE_NORMAL_ACCOUNT
, ATYPE_WORKSTATION_TRUST
,
914 ATYPE_INTERDOMAIN_TRUST
, u_filter
);
915 if (filter
== NULL
) {
916 return NT_STATUS_NO_MEMORY
;
919 TALLOC_FREE(u_filter
);
921 if (*g_filter
!= '\0') {
922 filter
= talloc_asprintf_append_buffer(
924 "(&(|(sAMAccountType=%d)(sAMAccountType=%d))(|%s))",
925 ATYPE_SECURITY_GLOBAL_GROUP
,
926 ATYPE_SECURITY_LOCAL_GROUP
,
928 if (filter
== NULL
) {
929 return NT_STATUS_NO_MEMORY
;
932 TALLOC_FREE(g_filter
);
934 filter
= talloc_asprintf_append_buffer(filter
, ")");
935 if (filter
== NULL
) {
936 return NT_STATUS_NO_MEMORY
;
939 DBG_DEBUG("Filter: [%s]\n", filter
);
941 rc
= tldap_search(ctx
->ld
, ctx
->default_nc
, TLDAP_SCOPE_SUB
, filter
,
942 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
943 0, 0, 0, talloc_tos(), &msgs
);
944 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
945 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
950 num_msgs
= talloc_array_length(msgs
);
952 for (i
=0; i
<num_msgs
; i
++) {
953 struct tldap_message
*msg
= msgs
[i
];
961 struct dom_sid_buf sidbuf
;
963 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
967 ok
= tldap_entry_dn(msg
, &dn
);
969 DBG_DEBUG("No dn found in msg %zu\n", i
);
973 ok
= idmap_ad_dn_filter(dom
, dn
);
975 DBG_DEBUG("%s filtered out\n", dn
);
979 ok
= tldap_pull_uint32(msg
, "sAMAccountType", &atype
);
981 DBG_DEBUG("No atype in object %s\n", dn
);
985 switch (atype
& 0xF0000000) {
986 case ATYPE_SECURITY_GLOBAL_GROUP
:
987 case ATYPE_SECURITY_LOCAL_GROUP
:
990 case ATYPE_NORMAL_ACCOUNT
:
991 case ATYPE_WORKSTATION_TRUST
:
992 case ATYPE_INTERDOMAIN_TRUST
:
996 DBG_WARNING("unrecognized SAM account type %08x\n",
1001 ok
= tldap_pull_uint32(msg
, (type
== ID_TYPE_UID
) ?
1002 ctx
->schema
->uid
: ctx
->schema
->gid
,
1005 DBG_WARNING("No unix id in object %s\n", dn
);
1009 ok
= tldap_pull_binsid(msg
, "objectSid", &sid
);
1011 DBG_DEBUG("No objectSid in object %s\n", dn
);
1016 for (j
=0; ids
[j
]; j
++) {
1017 if ((type
== ids
[j
]->xid
.type
) &&
1018 (xid
== ids
[j
]->xid
.id
)) {
1024 DBG_DEBUG("Got unexpected sid %s from object %s\n",
1025 dom_sid_str_buf(&sid
, &sidbuf
),
1030 sid_copy(map
->sid
, &sid
);
1031 map
->status
= ID_MAPPED
;
1033 DBG_DEBUG("Mapped %s -> %ju (%d)\n",
1034 dom_sid_str_buf(map
->sid
, &sidbuf
),
1035 (uintmax_t)map
->xid
.id
, map
->xid
.type
);
1040 return NT_STATUS_OK
;
1043 static NTSTATUS
idmap_ad_sids_to_unixids(struct idmap_domain
*dom
,
1044 struct id_map
**ids
)
1046 struct idmap_ad_context
*ctx
;
1049 struct tldap_message
**msgs
;
1054 const char *attrs
[] = {
1057 NULL
, /* attr_uidnumber */
1058 NULL
, /* attr_gidnumber */
1061 status
= idmap_ad_get_context(dom
, &ctx
);
1062 if (!NT_STATUS_IS_OK(status
)) {
1066 attrs
[2] = ctx
->schema
->uid
;
1067 attrs
[3] = ctx
->schema
->gid
;
1069 filter
= talloc_asprintf(
1071 "(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)"
1072 "(sAMAccountType=%d)(sAMAccountType=%d))(|",
1073 ATYPE_NORMAL_ACCOUNT
, ATYPE_WORKSTATION_TRUST
,
1074 ATYPE_INTERDOMAIN_TRUST
, ATYPE_SECURITY_GLOBAL_GROUP
,
1075 ATYPE_SECURITY_LOCAL_GROUP
);
1076 if (filter
== NULL
) {
1077 return NT_STATUS_NO_MEMORY
;
1080 for (i
=0; ids
[i
]; i
++) {
1083 ids
[i
]->status
= ID_UNKNOWN
;
1085 sidstr
= ldap_encode_ndr_dom_sid(talloc_tos(), ids
[i
]->sid
);
1086 if (sidstr
== NULL
) {
1087 return NT_STATUS_NO_MEMORY
;
1090 filter
= talloc_asprintf_append_buffer(
1091 filter
, "(objectSid=%s)", sidstr
);
1092 TALLOC_FREE(sidstr
);
1093 if (filter
== NULL
) {
1094 return NT_STATUS_NO_MEMORY
;
1098 filter
= talloc_asprintf_append_buffer(filter
, "))");
1099 if (filter
== NULL
) {
1100 return NT_STATUS_NO_MEMORY
;
1103 DBG_DEBUG("Filter: [%s]\n", filter
);
1105 rc
= tldap_search(ctx
->ld
, ctx
->default_nc
, TLDAP_SCOPE_SUB
, filter
,
1106 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
1107 0, 0, 0, talloc_tos(), &msgs
);
1108 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
1109 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
1112 TALLOC_FREE(filter
);
1114 num_msgs
= talloc_array_length(msgs
);
1116 for (i
=0; i
<num_msgs
; i
++) {
1117 struct tldap_message
*msg
= msgs
[i
];
1123 uint64_t account_type
, xid
;
1125 struct dom_sid_buf buf
;
1127 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
1131 ok
= tldap_entry_dn(msg
, &dn
);
1133 DBG_DEBUG("No dn found in msg %zu\n", i
);
1137 ok
= idmap_ad_dn_filter(dom
, dn
);
1139 DBG_DEBUG("%s filtered out\n", dn
);
1143 ok
= tldap_pull_binsid(msg
, "objectSid", &sid
);
1145 DBG_DEBUG("No objectSid in object %s\n", dn
);
1150 for (j
=0; ids
[j
]; j
++) {
1151 if (dom_sid_equal(&sid
, ids
[j
]->sid
)) {
1157 DBG_DEBUG("Got unexpected sid %s from object %s\n",
1158 dom_sid_str_buf(&sid
, &buf
),
1163 ok
= tldap_pull_uint64(msg
, "sAMAccountType", &account_type
);
1165 DBG_DEBUG("No sAMAccountType in %s\n", dn
);
1169 switch (account_type
& 0xF0000000) {
1170 case ATYPE_SECURITY_GLOBAL_GROUP
:
1171 case ATYPE_SECURITY_LOCAL_GROUP
:
1174 case ATYPE_NORMAL_ACCOUNT
:
1175 case ATYPE_WORKSTATION_TRUST
:
1176 case ATYPE_INTERDOMAIN_TRUST
:
1180 DBG_WARNING("unrecognized SAM account type %"PRIu64
"\n",
1185 ok
= tldap_pull_uint64(msg
,
1186 type
== ID_TYPE_UID
?
1187 ctx
->schema
->uid
: ctx
->schema
->gid
,
1190 DBG_DEBUG("No xid in %s\n", dn
);
1195 map
->xid
.type
= type
;
1197 map
->status
= ID_MAPPED
;
1199 DEBUG(10, ("Mapped %s -> %lu (%d)\n",
1200 dom_sid_str_buf(map
->sid
, &buf
),
1201 (unsigned long)map
->xid
.id
, map
->xid
.type
));
1206 return NT_STATUS_OK
;
1209 static NTSTATUS
idmap_ad_unixids_to_sids_retry(struct idmap_domain
*dom
,
1210 struct id_map
**ids
)
1212 const NTSTATUS status_server_down
=
1213 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN
));
1216 status
= idmap_ad_unixids_to_sids(dom
, ids
);
1218 if (NT_STATUS_EQUAL(status
, status_server_down
)) {
1219 TALLOC_FREE(dom
->private_data
);
1220 status
= idmap_ad_unixids_to_sids(dom
, ids
);
1226 static NTSTATUS
idmap_ad_sids_to_unixids_retry(struct idmap_domain
*dom
,
1227 struct id_map
**ids
)
1229 const NTSTATUS status_server_down
=
1230 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN
));
1233 status
= idmap_ad_sids_to_unixids(dom
, ids
);
1235 if (NT_STATUS_EQUAL(status
, status_server_down
)) {
1236 TALLOC_FREE(dom
->private_data
);
1237 status
= idmap_ad_sids_to_unixids(dom
, ids
);
1243 static const struct idmap_methods ad_methods
= {
1244 .init
= idmap_ad_initialize
,
1245 .unixids_to_sids
= idmap_ad_unixids_to_sids_retry
,
1246 .sids_to_unixids
= idmap_ad_sids_to_unixids_retry
,
1250 NTSTATUS
idmap_ad_init(TALLOC_CTX
*ctx
)
1254 status
= smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION
,
1256 if (!NT_STATUS_IS_OK(status
)) {
1260 status
= idmap_ad_nss_init(ctx
);
1261 if (!NT_STATUS_IS_OK(status
)) {
1265 return NT_STATUS_OK
;