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"
41 #include "source4/lib/tls/tls.h"
43 struct idmap_ad_schema_names
;
45 struct idmap_ad_context
{
46 struct idmap_domain
*dom
;
47 struct tldap_context
*ld
;
48 struct idmap_ad_schema_names
*schema
;
49 const char *default_nc
;
51 bool unix_primary_group
;
54 struct ldb_context
*ldb
;
55 struct ldb_dn
**deny_ous
;
56 struct ldb_dn
**allow_ous
;
59 static NTSTATUS
idmap_ad_get_context(struct idmap_domain
*dom
,
60 struct idmap_ad_context
**pctx
);
62 static char *get_schema_path(TALLOC_CTX
*mem_ctx
, struct tldap_context
*ld
)
64 struct tldap_message
*rootdse
;
66 rootdse
= tldap_rootdse(ld
);
67 if (rootdse
== NULL
) {
71 return tldap_talloc_single_attribute(rootdse
, "schemaNamingContext",
75 static char *get_default_nc(TALLOC_CTX
*mem_ctx
, struct tldap_context
*ld
)
77 struct tldap_message
*rootdse
;
79 rootdse
= tldap_rootdse(ld
);
80 if (rootdse
== NULL
) {
84 return tldap_talloc_single_attribute(rootdse
, "defaultNamingContext",
88 struct idmap_ad_schema_names
{
97 static TLDAPRC
get_attrnames_by_oids(struct tldap_context
*ld
,
99 const char *schema_path
,
105 const char *attrs
[] = { "lDAPDisplayName", "attributeId" };
108 struct tldap_message
**msgs
;
111 filter
= talloc_strdup(mem_ctx
, "(|");
113 for (i
=0; i
<num_oids
; i
++) {
114 talloc_asprintf_addbuf(&filter
, "(attributeId=%s)", oids
[i
]);
116 talloc_asprintf_addbuf(&filter
, ")");
118 if (filter
== NULL
) {
119 return TLDAP_NO_MEMORY
;
122 rc
= tldap_search(ld
, schema_path
, TLDAP_SCOPE_SUB
, filter
,
123 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
124 0, 0, 0, mem_ctx
, &msgs
);;
126 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
130 for (i
=0; i
<num_oids
; i
++) {
134 num_msgs
= talloc_array_length(msgs
);
136 for (i
=0; i
<num_msgs
; i
++) {
137 struct tldap_message
*msg
= msgs
[i
];
141 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
142 /* Could be a TLDAP_RES_SEARCH_REFERENCE */
146 oid
= tldap_talloc_single_attribute(
147 msg
, "attributeId", msg
);
152 for (j
=0; j
<num_oids
; j
++) {
153 if (strequal(oid
, oids
[j
])) {
164 names
[j
] = tldap_talloc_single_attribute(
165 msg
, "lDAPDisplayName", mem_ctx
);
169 for (i
=0; i
<num_oids
; i
++) {
170 if (names
[i
] == NULL
) {
171 DBG_ERR("Failed to retrieve schema name for "
172 "oid [%s]. Schema mode is incorrect "
173 "for this domain.\n", oids
[i
]);
174 return TLDAP_FILTER_ERROR
;
178 return TLDAP_SUCCESS
;
181 static TLDAPRC
get_posix_schema_names(struct tldap_context
*ld
,
182 const char *schema_mode
,
184 struct idmap_ad_schema_names
**pschema
)
187 struct idmap_ad_schema_names
*schema
;
189 const char *oids_sfu
[] = {
190 ADS_ATTR_SFU_UIDNUMBER_OID
,
191 ADS_ATTR_SFU_GIDNUMBER_OID
,
192 ADS_ATTR_SFU_HOMEDIR_OID
,
193 ADS_ATTR_SFU_SHELL_OID
,
194 ADS_ATTR_SFU_GECOS_OID
,
197 const char *oids_sfu20
[] = {
198 ADS_ATTR_SFU20_UIDNUMBER_OID
,
199 ADS_ATTR_SFU20_GIDNUMBER_OID
,
200 ADS_ATTR_SFU20_HOMEDIR_OID
,
201 ADS_ATTR_SFU20_SHELL_OID
,
202 ADS_ATTR_SFU20_GECOS_OID
,
203 ADS_ATTR_SFU20_UID_OID
205 const char *oids_rfc2307
[] = {
206 ADS_ATTR_RFC2307_UIDNUMBER_OID
,
207 ADS_ATTR_RFC2307_GIDNUMBER_OID
,
208 ADS_ATTR_RFC2307_HOMEDIR_OID
,
209 ADS_ATTR_RFC2307_SHELL_OID
,
210 ADS_ATTR_RFC2307_GECOS_OID
,
211 ADS_ATTR_RFC2307_UID_OID
217 schema
= talloc(mem_ctx
, struct idmap_ad_schema_names
);
218 if (schema
== NULL
) {
219 return TLDAP_NO_MEMORY
;
222 schema_path
= get_schema_path(schema
, ld
);
223 if (schema_path
== NULL
) {
225 return TLDAP_NO_MEMORY
;
230 if ((schema_mode
!= NULL
) && (schema_mode
[0] != '\0')) {
231 if (strequal(schema_mode
, "sfu")) {
233 } else if (strequal(schema_mode
, "sfu20")) {
235 } else if (strequal(schema_mode
, "rfc2307" )) {
238 DBG_WARNING("Unknown schema mode %s\n", schema_mode
);
242 rc
= get_attrnames_by_oids(ld
, schema
, schema_path
, 6, oids
, names
);
243 TALLOC_FREE(schema_path
);
244 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
249 schema
->uid
= names
[0];
250 schema
->gid
= names
[1];
251 schema
->dir
= names
[2];
252 schema
->shell
= names
[3];
253 schema
->gecos
= names
[4];
254 schema
->name
= names
[5];
258 return TLDAP_SUCCESS
;
261 static void PRINTF_ATTRIBUTE(3, 0) idmap_ad_tldap_debug(
263 enum tldap_debug_level level
,
267 int samba_level
= -1;
270 case TLDAP_DEBUG_FATAL
:
271 samba_level
= DBGLVL_ERR
;
273 case TLDAP_DEBUG_ERROR
:
274 samba_level
= DBGLVL_ERR
;
276 case TLDAP_DEBUG_WARNING
:
277 samba_level
= DBGLVL_WARNING
;
279 case TLDAP_DEBUG_TRACE
:
280 samba_level
= DBGLVL_DEBUG
;
284 if (CHECK_DEBUGLVL(samba_level
)) {
288 ret
= vasprintf(&s
, fmt
, ap
);
292 DEBUG(samba_level
, ("idmap_ad_tldap: %s", s
));
297 static NTSTATUS
idmap_ad_get_tldap_ctx(TALLOC_CTX
*mem_ctx
,
299 struct tldap_context
**pld
)
301 struct netr_DsRGetDCNameInfo
*dcinfo
;
302 struct sockaddr_storage dcaddr
= {
303 .ss_family
= AF_UNSPEC
,
305 struct sockaddr_storage
*pdcaddr
= NULL
;
306 struct winbindd_domain
*creds_domain
= NULL
;
307 struct cli_credentials
*creds
;
308 struct loadparm_context
*lp_ctx
;
309 struct tldap_context
*ld
;
311 bool use_tls
= false;
312 bool use_starttls
= false;
314 uint32_t gensec_features
= 0;
315 char *sitename
= NULL
;
321 wrap_flags
= lp_client_ldap_sasl_wrapping();
323 if (wrap_flags
& ADS_AUTH_SASL_LDAPS
) {
326 } else if (wrap_flags
& ADS_AUTH_SASL_STARTTLS
) {
330 if (wrap_flags
& ADS_AUTH_SASL_SEAL
) {
331 gensec_features
|= GENSEC_FEATURE_SEAL
;
333 if (wrap_flags
& ADS_AUTH_SASL_SIGN
) {
334 gensec_features
|= GENSEC_FEATURE_SIGN
;
337 if (gensec_features
!= 0) {
338 gensec_features
|= GENSEC_FEATURE_LDAP_STYLE
;
341 status
= wb_dsgetdcname_gencache_get(mem_ctx
, domname
, &dcinfo
);
342 if (!NT_STATUS_IS_OK(status
)) {
343 DBG_DEBUG("Could not get dcinfo for %s: %s\n", domname
,
348 if (dcinfo
->dc_unc
== NULL
) {
350 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
352 if (dcinfo
->dc_unc
[0] == '\\') {
355 if (dcinfo
->dc_unc
[0] == '\\') {
359 ok
= resolve_name(dcinfo
->dc_unc
, &dcaddr
, 0x20, true);
361 DBG_DEBUG("Could not resolve name %s\n", dcinfo
->dc_unc
);
363 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
366 sitename
= sitename_fetch(talloc_tos(), lp_realm());
369 * create_local_private_krb5_conf_for_domain() can deal with
372 if (strequal(domname
, lp_realm()) || strequal(domname
, lp_workgroup()))
377 ok
= create_local_private_krb5_conf_for_domain(
378 lp_realm(), lp_workgroup(), sitename
, pdcaddr
);
379 TALLOC_FREE(sitename
);
381 DBG_DEBUG("Could not create private krb5.conf\n");
383 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
;
386 status
= open_socket_out(&dcaddr
, tcp_port
, 10000, &fd
);
387 if (!NT_STATUS_IS_OK(status
)) {
388 DBG_DEBUG("open_socket_out failed: %s\n", nt_errstr(status
));
393 ld
= tldap_context_create(dcinfo
, fd
);
395 DBG_DEBUG("tldap_context_create failed\n");
398 return NT_STATUS_NO_MEMORY
;
400 tldap_set_debug(ld
, idmap_ad_tldap_debug
, NULL
);
403 * Here we use or own machine account as
404 * we run as domain member.
406 creds_domain
= find_our_domain();
407 if (creds_domain
== NULL
) {
408 DBG_ERR("find_our_domain() returned NULL\n");
410 return NT_STATUS_INTERNAL_ERROR
;
412 status
= winbindd_get_trust_credentials(creds_domain
,
414 false, /* netlogon */
415 false, /* ipc_fallback */
417 if (!NT_STATUS_IS_OK(status
)) {
418 DBG_ERR("winbindd_get_trust_credentials(%s) failed - %s\n",
419 creds_domain
->name
, nt_errstr(status
));
424 lp_ctx
= loadparm_init_s3(dcinfo
, loadparm_s3_helpers());
425 if (lp_ctx
== NULL
) {
426 DBG_DEBUG("loadparm_init_s3 failed\n");
428 return NT_STATUS_NO_MEMORY
;
431 if (use_tls
&& !tldap_has_tls_tstream(ld
)) {
432 struct tstream_tls_params
*tls_params
= NULL
;
435 rc
= tldap_extended(ld
,
436 LDB_EXTENDED_START_TLS_OID
,
445 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
446 DBG_ERR("tldap_extended(%s) failed: %s\n",
447 LDB_EXTENDED_START_TLS_OID
,
448 tldap_errstr(talloc_tos(), ld
, rc
));
449 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
453 status
= tstream_tls_params_client_lpcfg(talloc_tos(),
457 if (!NT_STATUS_IS_OK(status
)) {
458 DBG_ERR("tstream_tls_params_client_lpcfg failed: %s\n",
464 rc
= tldap_tls_connect(ld
, tls_params
);
465 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
466 DBG_ERR("tldap_gensec_bind(%s) failed: %s\n",
468 tldap_errstr(dcinfo
, ld
, rc
));
470 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
474 rc
= tldap_gensec_bind(ld
, creds
, "ldap", dcinfo
->dc_unc
, NULL
, lp_ctx
,
476 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
477 DBG_DEBUG("tldap_gensec_bind failed: %s\n",
478 tldap_errstr(dcinfo
, ld
, rc
));
480 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
483 rc
= tldap_fetch_rootdse(ld
);
484 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
485 DBG_DEBUG("tldap_fetch_rootdse failed: %s\n",
486 tldap_errstr(dcinfo
, ld
, rc
));
488 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
491 *pld
= talloc_move(mem_ctx
, &ld
);
496 static int idmap_ad_context_destructor(struct idmap_ad_context
*ctx
)
498 if ((ctx
->dom
!= NULL
) && (ctx
->dom
->private_data
== ctx
)) {
499 ctx
->dom
->private_data
= NULL
;
504 static struct ldb_dn
**str_list_to_dns(TALLOC_CTX
*mem_ctx
,
506 struct ldb_context
*ldb
,
507 const char **strlist
)
509 size_t i
, num_dns
= str_list_length(strlist
);
511 struct ldb_dn
**dns
= NULL
;
513 dns
= talloc_array(mem_ctx
, struct ldb_dn
*, num_dns
);
519 dbgstr
= talloc_strdup(talloc_tos(), "");
521 for (i
= 0; i
< num_dns
; i
++) {
522 dns
[i
] = ldb_dn_new(dns
, ldb
, strlist
[i
]);
523 if (dns
[i
] == NULL
) {
524 DBG_WARNING("ldb_dn_new(%s) failed\n", strlist
[i
]);
528 talloc_asprintf_addbuf(
531 ldb_dn_get_extended_linearized(dbgstr
, dns
[i
], 1));
534 DBG_DEBUG("%s %s\n", dbgmsg
, dbgstr
);
540 static NTSTATUS
idmap_ad_context_create(TALLOC_CTX
*mem_ctx
,
541 struct idmap_domain
*dom
,
543 struct idmap_ad_context
**pctx
)
545 struct idmap_ad_context
*ctx
;
546 const char *schema_mode
;
547 const char **allow
= NULL
;
548 const char **deny
= NULL
;
552 ctx
= talloc_zero(mem_ctx
, struct idmap_ad_context
);
554 return NT_STATUS_NO_MEMORY
;
558 talloc_set_destructor(ctx
, idmap_ad_context_destructor
);
560 status
= idmap_ad_get_tldap_ctx(ctx
, domname
, &ctx
->ld
);
561 if (!NT_STATUS_IS_OK(status
)) {
562 DBG_DEBUG("idmap_ad_get_tldap_ctx failed: %s\n",
568 ctx
->default_nc
= get_default_nc(ctx
, ctx
->ld
);
569 if (ctx
->default_nc
== NULL
) {
570 DBG_DEBUG("No default nc\n");
575 ctx
->unix_primary_group
= idmap_config_bool(
576 domname
, "unix_primary_group", false);
577 ctx
->unix_nss_info
= idmap_config_bool(
578 domname
, "unix_nss_info", false);
580 schema_mode
= idmap_config_const_string(
581 domname
, "schema_mode", "rfc2307");
583 rc
= get_posix_schema_names(ctx
->ld
, schema_mode
, ctx
, &ctx
->schema
);
584 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
585 DBG_DEBUG("get_posix_schema_names failed: %s\n",
586 tldap_errstr(ctx
, ctx
->ld
, rc
));
588 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
591 deny
= idmap_config_string_list(domname
, "deny ous", NULL
);
592 allow
= idmap_config_string_list(domname
, "allow ous", NULL
);
594 if ((deny
!= NULL
) || (allow
!= NULL
)) {
595 int ret
= ldb_global_init();
597 status
= map_nt_error_from_unix(errno
);
598 DBG_WARNING("ldb_global_init() failed: %s\n",
604 ctx
->ldb
= ldb_init(ctx
, global_event_context());
605 if (ctx
->ldb
== NULL
) {
606 status
= map_nt_error_from_unix(errno
);
607 DBG_WARNING("ldb_init() failed: %s\n", strerror(errno
));
614 ctx
->deny_ous
= str_list_to_dns(ctx
, "Denying", ctx
->ldb
, deny
);
615 if (ctx
->deny_ous
== NULL
) {
616 DBG_DEBUG("str_list_to_dns failed\n");
618 return NT_STATUS_NO_MEMORY
;
624 str_list_to_dns(ctx
, "Allowing", ctx
->ldb
, allow
);
625 if (ctx
->allow_ous
== NULL
) {
626 DBG_DEBUG("str_list_to_dns failed\n");
628 return NT_STATUS_NO_MEMORY
;
636 static bool check_dn(struct ldb_dn
**dns
, struct ldb_dn
*dn
)
638 size_t i
, num_dns
= talloc_array_length(dns
);
640 for (i
= 0; i
< num_dns
; i
++) {
641 struct ldb_dn
*base
= dns
[i
];
642 int ret
= ldb_dn_compare_base(base
, dn
);
650 static bool idmap_ad_dn_filter(struct idmap_domain
*dom
, const char *dnstr
)
652 struct idmap_ad_context
*ctx
= NULL
;
653 struct ldb_dn
*dn
= NULL
;
657 status
= idmap_ad_get_context(dom
, &ctx
);
658 if (!NT_STATUS_IS_OK(status
)) {
659 DBG_DEBUG("idmap_ad_get_context failed: %s\n",
664 if ((ctx
->allow_ous
== NULL
) && (ctx
->deny_ous
== NULL
)) {
671 dn
= ldb_dn_new(talloc_tos(), ctx
->ldb
, dnstr
);
673 DBG_DEBUG("ldb_dn_new(%s) failed\n", dnstr
);
677 if (ctx
->deny_ous
!= NULL
) {
678 bool denied
= check_dn(ctx
->deny_ous
, dn
);
680 DBG_WARNING("Denied %s\n", dnstr
);
685 if (ctx
->allow_ous
== NULL
) {
687 * Only a few denied OUs around, allow by
694 if (ctx
->allow_ous
!= NULL
) {
695 bool allowed
= check_dn(ctx
->allow_ous
, dn
);
699 DBG_WARNING("Did not allow %s\n", dnstr
);
705 static NTSTATUS
idmap_ad_query_user(struct idmap_domain
*domain
,
706 struct wbint_userinfo
*info
)
708 struct idmap_ad_context
*ctx
;
711 char *sidstr
, *filter
;
712 const char *attrs
[4];
714 struct tldap_message
**msgs
;
716 status
= idmap_ad_get_context(domain
, &ctx
);
717 if (!NT_STATUS_IS_OK(status
)) {
721 if (!(ctx
->unix_primary_group
|| ctx
->unix_nss_info
)) {
725 attrs
[0] = ctx
->schema
->gid
;
726 attrs
[1] = ctx
->schema
->gecos
;
727 attrs
[2] = ctx
->schema
->dir
;
728 attrs
[3] = ctx
->schema
->shell
;
730 sidstr
= ldap_encode_ndr_dom_sid(talloc_tos(), &info
->user_sid
);
731 if (sidstr
== NULL
) {
732 return NT_STATUS_NO_MEMORY
;
735 filter
= talloc_asprintf(talloc_tos(), "(objectsid=%s)", sidstr
);
737 if (filter
== NULL
) {
738 return NT_STATUS_NO_MEMORY
;
741 DBG_DEBUG("Filter: [%s]\n", filter
);
743 rc
= tldap_search(ctx
->ld
, ctx
->default_nc
, TLDAP_SCOPE_SUB
, filter
,
744 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
745 0, 0, 0, talloc_tos(), &msgs
);
746 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
747 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
752 num_msgs
= talloc_array_length(msgs
);
754 for (i
=0; i
<num_msgs
; i
++) {
755 struct tldap_message
*msg
= msgs
[i
];
759 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
762 ok
= tldap_entry_dn(msg
, &dn
);
766 ok
= idmap_ad_dn_filter(domain
, dn
);
768 DBG_DEBUG("%s filtered out\n", dn
);
772 if (ctx
->unix_primary_group
) {
775 ok
= tldap_pull_uint32(msg
, ctx
->schema
->gid
, &gid
);
777 DBG_DEBUG("Setting primary group "
778 "to %"PRIu32
" from attr %s\n",
779 gid
, ctx
->schema
->gid
);
780 info
->primary_gid
= gid
;
784 if (ctx
->unix_nss_info
) {
787 attr
= tldap_talloc_single_attribute(
788 msg
, ctx
->schema
->dir
, talloc_tos());
790 info
->homedir
= talloc_move(info
, &attr
);
794 attr
= tldap_talloc_single_attribute(
795 msg
, ctx
->schema
->shell
, talloc_tos());
797 info
->shell
= talloc_move(info
, &attr
);
801 attr
= tldap_talloc_single_attribute(
802 msg
, ctx
->schema
->gecos
, talloc_tos());
804 info
->full_name
= talloc_move(info
, &attr
);
813 static NTSTATUS
idmap_ad_query_user_retry(struct idmap_domain
*domain
,
814 struct wbint_userinfo
*info
)
816 const NTSTATUS status_server_down
=
817 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN
));
820 status
= idmap_ad_query_user(domain
, info
);
822 if (NT_STATUS_EQUAL(status
, status_server_down
)) {
823 TALLOC_FREE(domain
->private_data
);
824 status
= idmap_ad_query_user(domain
, info
);
830 static NTSTATUS
idmap_ad_initialize(struct idmap_domain
*dom
)
832 dom
->query_user
= idmap_ad_query_user_retry
;
833 dom
->private_data
= NULL
;
837 static NTSTATUS
idmap_ad_get_context(struct idmap_domain
*dom
,
838 struct idmap_ad_context
**pctx
)
840 struct idmap_ad_context
*ctx
= NULL
;
845 * Make sure we never try to use LDAP against
846 * a trusted domain as AD_DC.
848 * This shouldn't be called currently,
849 * but you never know what happens in future.
851 return NT_STATUS_REQUEST_NOT_ACCEPTED
;
854 if (dom
->private_data
!= NULL
) {
855 *pctx
= talloc_get_type_abort(dom
->private_data
,
856 struct idmap_ad_context
);
860 status
= idmap_ad_context_create(dom
, dom
, dom
->name
, &ctx
);
861 if (!NT_STATUS_IS_OK(status
)) {
862 DBG_DEBUG("idmap_ad_context_create failed: %s\n",
867 dom
->private_data
= ctx
;
872 static NTSTATUS
idmap_ad_unixids_to_sids(struct idmap_domain
*dom
,
875 struct idmap_ad_context
*ctx
;
878 struct tldap_message
**msgs
;
881 char *u_filter
, *g_filter
, *filter
;
883 const char *attrs
[] = {
886 NULL
, /* attr_uidnumber */
887 NULL
, /* attr_gidnumber */
890 status
= idmap_ad_get_context(dom
, &ctx
);
891 if (!NT_STATUS_IS_OK(status
)) {
895 attrs
[2] = ctx
->schema
->uid
;
896 attrs
[3] = ctx
->schema
->gid
;
898 u_filter
= talloc_strdup(talloc_tos(), "");
899 if (u_filter
== NULL
) {
900 return NT_STATUS_NO_MEMORY
;
903 g_filter
= talloc_strdup(talloc_tos(), "");
904 if (g_filter
== NULL
) {
905 return NT_STATUS_NO_MEMORY
;
908 for (i
=0; ids
[i
] != NULL
; i
++) {
909 struct id_map
*id
= ids
[i
];
911 id
->status
= ID_UNKNOWN
;
913 switch (id
->xid
.type
) {
915 u_filter
= talloc_asprintf_append_buffer(
916 u_filter
, "(%s=%ju)", ctx
->schema
->uid
,
917 (uintmax_t)id
->xid
.id
);
918 if (u_filter
== NULL
) {
919 return NT_STATUS_NO_MEMORY
;
925 g_filter
= talloc_asprintf_append_buffer(
926 g_filter
, "(%s=%ju)", ctx
->schema
->gid
,
927 (uintmax_t)id
->xid
.id
);
928 if (g_filter
== NULL
) {
929 return NT_STATUS_NO_MEMORY
;
935 DBG_WARNING("Unknown id type: %u\n",
936 (unsigned)id
->xid
.type
);
941 filter
= talloc_strdup(talloc_tos(), "(|");
942 if (filter
== NULL
) {
943 return NT_STATUS_NO_MEMORY
;
946 if (*u_filter
!= '\0') {
947 filter
= talloc_asprintf_append_buffer(
949 "(&(|(sAMAccountType=%d)(sAMAccountType=%d)"
950 "(sAMAccountType=%d))(|%s))",
951 ATYPE_NORMAL_ACCOUNT
, ATYPE_WORKSTATION_TRUST
,
952 ATYPE_INTERDOMAIN_TRUST
, u_filter
);
953 if (filter
== NULL
) {
954 return NT_STATUS_NO_MEMORY
;
957 TALLOC_FREE(u_filter
);
959 if (*g_filter
!= '\0') {
960 filter
= talloc_asprintf_append_buffer(
962 "(&(|(sAMAccountType=%d)(sAMAccountType=%d))(|%s))",
963 ATYPE_SECURITY_GLOBAL_GROUP
,
964 ATYPE_SECURITY_LOCAL_GROUP
,
966 if (filter
== NULL
) {
967 return NT_STATUS_NO_MEMORY
;
970 TALLOC_FREE(g_filter
);
972 filter
= talloc_asprintf_append_buffer(filter
, ")");
973 if (filter
== NULL
) {
974 return NT_STATUS_NO_MEMORY
;
977 DBG_DEBUG("Filter: [%s]\n", filter
);
979 rc
= tldap_search(ctx
->ld
, ctx
->default_nc
, TLDAP_SCOPE_SUB
, filter
,
980 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
981 0, 0, 0, talloc_tos(), &msgs
);
982 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
983 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
988 num_msgs
= talloc_array_length(msgs
);
990 for (i
=0; i
<num_msgs
; i
++) {
991 struct tldap_message
*msg
= msgs
[i
];
999 struct dom_sid_buf sidbuf
;
1001 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
1005 ok
= tldap_entry_dn(msg
, &dn
);
1007 DBG_DEBUG("No dn found in msg %zu\n", i
);
1011 ok
= idmap_ad_dn_filter(dom
, dn
);
1013 DBG_DEBUG("%s filtered out\n", dn
);
1017 ok
= tldap_pull_uint32(msg
, "sAMAccountType", &atype
);
1019 DBG_DEBUG("No atype in object %s\n", dn
);
1023 switch (atype
& 0xF0000000) {
1024 case ATYPE_SECURITY_GLOBAL_GROUP
:
1025 case ATYPE_SECURITY_LOCAL_GROUP
:
1028 case ATYPE_NORMAL_ACCOUNT
:
1029 case ATYPE_WORKSTATION_TRUST
:
1030 case ATYPE_INTERDOMAIN_TRUST
:
1034 DBG_WARNING("unrecognized SAM account type %08x\n",
1039 ok
= tldap_pull_uint32(msg
, (type
== ID_TYPE_UID
) ?
1040 ctx
->schema
->uid
: ctx
->schema
->gid
,
1043 DBG_WARNING("No unix id in object %s\n", dn
);
1047 ok
= tldap_pull_binsid(msg
, "objectSid", &sid
);
1049 DBG_DEBUG("No objectSid in object %s\n", dn
);
1054 for (j
=0; ids
[j
]; j
++) {
1055 if ((type
== ids
[j
]->xid
.type
) &&
1056 (xid
== ids
[j
]->xid
.id
)) {
1062 DBG_DEBUG("Got unexpected sid %s from object %s\n",
1063 dom_sid_str_buf(&sid
, &sidbuf
),
1068 sid_copy(map
->sid
, &sid
);
1069 map
->status
= ID_MAPPED
;
1071 DBG_DEBUG("Mapped %s -> %ju (%d)\n",
1072 dom_sid_str_buf(map
->sid
, &sidbuf
),
1073 (uintmax_t)map
->xid
.id
, map
->xid
.type
);
1078 return NT_STATUS_OK
;
1081 static NTSTATUS
idmap_ad_sids_to_unixids(struct idmap_domain
*dom
,
1082 struct id_map
**ids
)
1084 struct idmap_ad_context
*ctx
;
1087 struct tldap_message
**msgs
;
1092 const char *attrs
[] = {
1095 NULL
, /* attr_uidnumber */
1096 NULL
, /* attr_gidnumber */
1099 status
= idmap_ad_get_context(dom
, &ctx
);
1100 if (!NT_STATUS_IS_OK(status
)) {
1104 attrs
[2] = ctx
->schema
->uid
;
1105 attrs
[3] = ctx
->schema
->gid
;
1107 filter
= talloc_asprintf(
1109 "(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)"
1110 "(sAMAccountType=%d)(sAMAccountType=%d))(|",
1111 ATYPE_NORMAL_ACCOUNT
, ATYPE_WORKSTATION_TRUST
,
1112 ATYPE_INTERDOMAIN_TRUST
, ATYPE_SECURITY_GLOBAL_GROUP
,
1113 ATYPE_SECURITY_LOCAL_GROUP
);
1114 if (filter
== NULL
) {
1115 return NT_STATUS_NO_MEMORY
;
1118 for (i
=0; ids
[i
]; i
++) {
1121 ids
[i
]->status
= ID_UNKNOWN
;
1123 sidstr
= ldap_encode_ndr_dom_sid(talloc_tos(), ids
[i
]->sid
);
1124 if (sidstr
== NULL
) {
1125 return NT_STATUS_NO_MEMORY
;
1128 filter
= talloc_asprintf_append_buffer(
1129 filter
, "(objectSid=%s)", sidstr
);
1130 TALLOC_FREE(sidstr
);
1131 if (filter
== NULL
) {
1132 return NT_STATUS_NO_MEMORY
;
1136 filter
= talloc_asprintf_append_buffer(filter
, "))");
1137 if (filter
== NULL
) {
1138 return NT_STATUS_NO_MEMORY
;
1141 DBG_DEBUG("Filter: [%s]\n", filter
);
1143 rc
= tldap_search(ctx
->ld
, ctx
->default_nc
, TLDAP_SCOPE_SUB
, filter
,
1144 attrs
, ARRAY_SIZE(attrs
), 0, NULL
, 0, NULL
, 0,
1145 0, 0, 0, talloc_tos(), &msgs
);
1146 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
1147 return NT_STATUS_LDAP(TLDAP_RC_V(rc
));
1150 TALLOC_FREE(filter
);
1152 num_msgs
= talloc_array_length(msgs
);
1154 for (i
=0; i
<num_msgs
; i
++) {
1155 struct tldap_message
*msg
= msgs
[i
];
1161 uint64_t account_type
, xid
;
1163 struct dom_sid_buf buf
;
1165 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
1169 ok
= tldap_entry_dn(msg
, &dn
);
1171 DBG_DEBUG("No dn found in msg %zu\n", i
);
1175 ok
= idmap_ad_dn_filter(dom
, dn
);
1177 DBG_DEBUG("%s filtered out\n", dn
);
1181 ok
= tldap_pull_binsid(msg
, "objectSid", &sid
);
1183 DBG_DEBUG("No objectSid in object %s\n", dn
);
1188 for (j
=0; ids
[j
]; j
++) {
1189 if (dom_sid_equal(&sid
, ids
[j
]->sid
)) {
1195 DBG_DEBUG("Got unexpected sid %s from object %s\n",
1196 dom_sid_str_buf(&sid
, &buf
),
1201 ok
= tldap_pull_uint64(msg
, "sAMAccountType", &account_type
);
1203 DBG_DEBUG("No sAMAccountType in %s\n", dn
);
1207 switch (account_type
& 0xF0000000) {
1208 case ATYPE_SECURITY_GLOBAL_GROUP
:
1209 case ATYPE_SECURITY_LOCAL_GROUP
:
1212 case ATYPE_NORMAL_ACCOUNT
:
1213 case ATYPE_WORKSTATION_TRUST
:
1214 case ATYPE_INTERDOMAIN_TRUST
:
1218 DBG_WARNING("unrecognized SAM account type %"PRIu64
"\n",
1223 ok
= tldap_pull_uint64(msg
,
1224 type
== ID_TYPE_UID
?
1225 ctx
->schema
->uid
: ctx
->schema
->gid
,
1228 DBG_DEBUG("No xid in %s\n", dn
);
1233 map
->xid
.type
= type
;
1235 map
->status
= ID_MAPPED
;
1237 DEBUG(10, ("Mapped %s -> %lu (%d)\n",
1238 dom_sid_str_buf(map
->sid
, &buf
),
1239 (unsigned long)map
->xid
.id
, map
->xid
.type
));
1244 return NT_STATUS_OK
;
1247 static NTSTATUS
idmap_ad_unixids_to_sids_retry(struct idmap_domain
*dom
,
1248 struct id_map
**ids
)
1250 const NTSTATUS status_server_down
=
1251 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN
));
1254 status
= idmap_ad_unixids_to_sids(dom
, ids
);
1256 if (NT_STATUS_EQUAL(status
, status_server_down
)) {
1257 TALLOC_FREE(dom
->private_data
);
1258 status
= idmap_ad_unixids_to_sids(dom
, ids
);
1264 static NTSTATUS
idmap_ad_sids_to_unixids_retry(struct idmap_domain
*dom
,
1265 struct id_map
**ids
)
1267 const NTSTATUS status_server_down
=
1268 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN
));
1271 status
= idmap_ad_sids_to_unixids(dom
, ids
);
1273 if (NT_STATUS_EQUAL(status
, status_server_down
)) {
1274 TALLOC_FREE(dom
->private_data
);
1275 status
= idmap_ad_sids_to_unixids(dom
, ids
);
1281 static const struct idmap_methods ad_methods
= {
1282 .init
= idmap_ad_initialize
,
1283 .unixids_to_sids
= idmap_ad_unixids_to_sids_retry
,
1284 .sids_to_unixids
= idmap_ad_sids_to_unixids_retry
,
1288 NTSTATUS
idmap_ad_init(TALLOC_CTX
*ctx
)
1292 status
= smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION
,
1294 if (!NT_STATUS_IS_OK(status
)) {
1298 status
= idmap_ad_nss_init(ctx
);
1299 if (!NT_STATUS_IS_OK(status
)) {
1303 return NT_STATUS_OK
;