1 /*
2 Unix SMB/CIFS implementation.
3
4 Winbind ADS backend functions
5
6 Copyright (C) Andrew Tridgell 2001
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
8 Copyright (C) Gerald (Jerry) Carter 2004
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "winbindd.h"
26 #include "winbindd_ads.h"
27 #include "libsmb/namequery.h"
28 #include "rpc_client/rpc_client.h"
29 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
30 #include "../libds/common/flags.h"
31 #include "ads.h"
32 #include "../libcli/ldap/ldap_ndr.h"
33 #include "../libcli/security/security.h"
34 #include "../libds/common/flag_mapping.h"
35 #include "libsmb/samlogon_cache.h"
36 #include "passdb.h"
37
38 #ifdef HAVE_ADS
39
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_WINBIND
42
43 extern struct winbindd_methods reconnect_methods;
44 extern struct winbindd_methods msrpc_methods;
45
46 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
47
48 /**
49 * Check if cached connection can be reused. If the connection cannot
50 * be reused the ADS_STRUCT is freed and the pointer is set to NULL.
51 */
ads_cached_connection_reuse(ADS_STRUCT ** adsp)52 static void ads_cached_connection_reuse(ADS_STRUCT **adsp)
53 {
54
55 ADS_STRUCT *ads = *adsp;
56
57 if (ads != NULL) {
58 time_t expire;
59 time_t now = time(NULL);
60
61 expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
62
63 DEBUG(7, ("Current tickets expire in %d seconds (at %d, time "
64 "is now %d)\n", (uint32_t)expire - (uint32_t)now,
65 (uint32_t) expire, (uint32_t) now));
66
67 if ( ads->config.realm && (expire > now)) {
68 return;
69 } else {
70 /* we own this ADS_STRUCT so make sure it goes away */
71 DEBUG(7,("Deleting expired krb5 credential cache\n"));
72 ads->is_mine = True;
73 ads_destroy( &ads );
74 ads_kdestroy(WINBIND_CCACHE_NAME);
75 *adsp = NULL;
76 }
77 }
78 }
79
80 /**
81 * @brief Establish a connection to a DC
82 *
83 * @param[out] adsp ADS_STRUCT that will be created
84 * @param[in] target_realm Realm of domain to connect to
85 * @param[in] target_dom_name 'workgroup' name of domain to connect to
86 * @param[in] ldap_server DNS name of server to connect to
87 * @param[in] password Our machine acount secret
88 * @param[in] auth_realm Realm of local domain for creating krb token
89 * @param[in] renewable Renewable ticket time
90 *
91 * @return ADS_STATUS
92 */
ads_cached_connection_connect(ADS_STRUCT ** adsp,const char * target_realm,const char * target_dom_name,const char * ldap_server,char * password,char * auth_realm,time_t renewable)93 static ADS_STATUS ads_cached_connection_connect(ADS_STRUCT **adsp,
94 const char *target_realm,
95 const char *target_dom_name,
96 const char *ldap_server,
97 char *password,
98 char *auth_realm,
99 time_t renewable)
100 {
101 ADS_STRUCT *ads;
102 ADS_STATUS status;
103 struct sockaddr_storage dc_ss;
104 fstring dc_name;
105
106 if (auth_realm == NULL) {
107 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
108 }
109
110 /* we don't want this to affect the users ccache */
111 setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
112
113 ads = ads_init(target_realm,
114 target_dom_name,
115 ldap_server,
116 ADS_SASL_SEAL);
117 if (!ads) {
118 DEBUG(1,("ads_init for domain %s failed\n", target_dom_name));
119 return ADS_ERROR(LDAP_NO_MEMORY);
120 }
121
122 SAFE_FREE(ads->auth.password);
123 SAFE_FREE(ads->auth.realm);
124
125 ads->auth.renewable = renewable;
126 ads->auth.password = password;
127
128 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
129
130 ads->auth.realm = SMB_STRDUP(auth_realm);
131 if (!strupper_m(ads->auth.realm)) {
132 ads_destroy(&ads);
133 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
134 }
135
136 /* Setup the server affinity cache. We don't reaally care
137 about the name. Just setup affinity and the KRB5_CONFIG
138 file. */
139 get_dc_name(ads->server.workgroup, ads->server.realm, dc_name, &dc_ss);
140
141 status = ads_connect(ads);
142 if (!ADS_ERR_OK(status)) {
143 DEBUG(1,("ads_connect for domain %s failed: %s\n",
144 target_dom_name, ads_errstr(status)));
145 ads_destroy(&ads);
146 return status;
147 }
148
149 /* set the flag that says we don't own the memory even
150 though we do so that ads_destroy() won't destroy the
151 structure we pass back by reference */
152
153 ads->is_mine = False;
154
155 *adsp = ads;
156
157 return status;
158 }
159
ads_idmap_cached_connection(ADS_STRUCT ** adsp,const char * dom_name)160 ADS_STATUS ads_idmap_cached_connection(ADS_STRUCT **adsp, const char *dom_name)
161 {
162 char *ldap_server, *realm, *password;
163 struct winbindd_domain *wb_dom;
164 ADS_STATUS status;
165
166 if (IS_AD_DC) {
167 /*
168 * Make sure we never try to use LDAP against
169 * a trusted domain as AD DC.
170 */
171 return ADS_ERROR_NT(NT_STATUS_REQUEST_NOT_ACCEPTED);
172 }
173
174 ads_cached_connection_reuse(adsp);
175 if (*adsp != NULL) {
176 return ADS_SUCCESS;
177 }
178
179 /*
180 * At this point we only have the NetBIOS domain name.
181 * Check if we can get server nam and realm from SAF cache
182 * and the domain list.
183 */
184 ldap_server = saf_fetch(talloc_tos(), dom_name);
185 DEBUG(10, ("ldap_server from saf cache: '%s'\n",
186 ldap_server ? ldap_server : ""));
187
188 wb_dom = find_domain_from_name(dom_name);
189 if (wb_dom == NULL) {
190 DEBUG(10, ("could not find domain '%s'\n", dom_name));
191 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
192 }
193
194 DEBUG(10, ("find_domain_from_name found realm '%s' for "
195 " domain '%s'\n", wb_dom->alt_name, dom_name));
196
197 if (!get_trust_pw_clear(dom_name, &password, NULL, NULL)) {
198 TALLOC_FREE(ldap_server);
199 return ADS_ERROR_NT(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
200 }
201
202 if (IS_DC) {
203 SMB_ASSERT(wb_dom->alt_name != NULL);
204 realm = SMB_STRDUP(wb_dom->alt_name);
205 } else {
206 struct winbindd_domain *our_domain = wb_dom;
207
208 /* always give preference to the alt_name in our
209 primary domain if possible */
210
211 if (!wb_dom->primary) {
212 our_domain = find_our_domain();
213 }
214
215 if (our_domain->alt_name != NULL) {
216 realm = SMB_STRDUP(our_domain->alt_name);
217 } else {
218 realm = SMB_STRDUP(lp_realm());
219 }
220 }
221
222 status = ads_cached_connection_connect(
223 adsp, /* Returns ads struct. */
224 wb_dom->alt_name, /* realm to connect to. */
225 dom_name, /* 'workgroup' name for ads_init */
226 ldap_server, /* DNS name to connect to. */
227 password, /* password for auth realm. */
228 realm, /* realm used for krb5 ticket. */
229 0); /* renewable ticket time. */
230
231 SAFE_FREE(realm);
232 TALLOC_FREE(ldap_server);
233
234 return status;
235 }
236
237 /*
238 return our ads connections structure for a domain. We keep the connection
239 open to make things faster
240 */
ads_cached_connection(struct winbindd_domain * domain)241 static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
242 {
243 ADS_STATUS status;
244 char *password, *realm;
245
246 if (IS_AD_DC) {
247 /*
248 * Make sure we never try to use LDAP against
249 * a trusted domain as AD DC.
250 */
251 return NULL;
252 }
253
254 DEBUG(10,("ads_cached_connection\n"));
255 ads_cached_connection_reuse((ADS_STRUCT **)&domain->private_data);
256
257 if (domain->private_data) {
258 return (ADS_STRUCT *)domain->private_data;
259 }
260
261 /* the machine acct password might have change - fetch it every time */
262
263 if (!get_trust_pw_clear(domain->name, &password, NULL, NULL)) {
264 return NULL;
265 }
266
267 if ( IS_DC ) {
268 SMB_ASSERT(domain->alt_name != NULL);
269 realm = SMB_STRDUP(domain->alt_name);
270 }
271 else {
272 struct winbindd_domain *our_domain = domain;
273
274
275 /* always give preference to the alt_name in our
276 primary domain if possible */
277
278 if ( !domain->primary )
279 our_domain = find_our_domain();
280
281 if (our_domain->alt_name != NULL) {
282 realm = SMB_STRDUP( our_domain->alt_name );
283 }
284 else
285 realm = SMB_STRDUP( lp_realm() );
286 }
287
288 status = ads_cached_connection_connect(
289 (ADS_STRUCT **)&domain->private_data,
290 domain->alt_name,
291 domain->name, NULL,
292 password, realm,
293 WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
294 SAFE_FREE(realm);
295
296 if (!ADS_ERR_OK(status)) {
297 /* if we get ECONNREFUSED then it might be a NT4
298 server, fall back to MSRPC */
299 if (status.error_type == ENUM_ADS_ERROR_SYSTEM &&
300 status.err.rc == ECONNREFUSED) {
301 /* 'reconnect_methods' is the MS-RPC backend. */
302 DEBUG(1,("Trying MSRPC methods\n"));
303 domain->backend = &reconnect_methods;
304 }
305 return NULL;
306 }
307
308 return (ADS_STRUCT *)domain->private_data;
309 }
310
311 /* Query display info for a realm. This is the basic user list fn */
query_user_list(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t ** prids)312 static NTSTATUS query_user_list(struct winbindd_domain *domain,
313 TALLOC_CTX *mem_ctx,
314 uint32_t **prids)
315 {
316 ADS_STRUCT *ads = NULL;
317 const char *attrs[] = { "sAMAccountType", "objectSid", NULL };
318 int count;
319 uint32_t *rids = NULL;
320 ADS_STATUS rc;
321 LDAPMessage *res = NULL;
322 LDAPMessage *msg = NULL;
323 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
324
325 DEBUG(3,("ads: query_user_list\n"));
326
327 if ( !winbindd_can_contact_domain( domain ) ) {
328 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
329 domain->name));
330 return NT_STATUS_OK;
331 }
332
333 ads = ads_cached_connection(domain);
334
335 if (!ads) {
336 domain->last_status = NT_STATUS_SERVER_DISABLED;
337 goto done;
338 }
339
340 rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
341 if (!ADS_ERR_OK(rc)) {
342 DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
343 status = ads_ntstatus(rc);
344 goto done;
345 } else if (!res) {
346 DEBUG(1,("query_user_list ads_search returned NULL res\n"));
347 goto done;
348 }
349
350 count = ads_count_replies(ads, res);
351 if (count == 0) {
352 DEBUG(1,("query_user_list: No users found\n"));
353 goto done;
354 }
355
356 rids = talloc_zero_array(mem_ctx, uint32_t, count);
357 if (rids == NULL) {
358 status = NT_STATUS_NO_MEMORY;
359 goto done;
360 }
361
362 count = 0;
363
364 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
365 struct dom_sid user_sid;
366 uint32_t atype;
367 bool ok;
368
369 ok = ads_pull_uint32(ads, msg, "sAMAccountType", &atype);
370 if (!ok) {
371 DBG_INFO("Object lacks sAMAccountType attribute\n");
372 continue;
373 }
374 if (ds_atype_map(atype) != SID_NAME_USER) {
375 DBG_INFO("Not a user account? atype=0x%x\n", atype);
376 continue;
377 }
378
379 if (!ads_pull_sid(ads, msg, "objectSid", &user_sid)) {
380 char *dn = ads_get_dn(ads, talloc_tos(), msg);
381 DBG_INFO("No sid for %s !?\n", dn);
382 TALLOC_FREE(dn);
383 continue;
384 }
385
386 if (!dom_sid_in_domain(&domain->sid, &user_sid)) {
387 struct dom_sid_buf sidstr, domstr;
388 DBG_WARNING("Got sid %s in domain %s\n",
389 dom_sid_str_buf(&user_sid, &sidstr),
390 dom_sid_str_buf(&domain->sid, &domstr));
391 continue;
392 }
393
394 sid_split_rid(&user_sid, &rids[count]);
395 count += 1;
396 }
397
398 rids = talloc_realloc(mem_ctx, rids, uint32_t, count);
399 if (prids != NULL) {
400 *prids = rids;
401 }
402
403 status = NT_STATUS_OK;
404
405 DBG_NOTICE("ads query_user_list gave %d entries\n", count);
406
407 done:
408 ads_msgfree(ads, res);
409 return status;
410 }
411
412 /* list all domain groups */
enum_dom_groups(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t * num_entries,struct wb_acct_info ** info)413 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
414 TALLOC_CTX *mem_ctx,
415 uint32_t *num_entries,
416 struct wb_acct_info **info)
417 {
418 ADS_STRUCT *ads = NULL;
419 const char *attrs[] = {"userPrincipalName", "sAMAccountName",
420 "name", "objectSid", NULL};
421 int i, count;
422 ADS_STATUS rc;
423 LDAPMessage *res = NULL;
424 LDAPMessage *msg = NULL;
425 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
426 const char *filter;
427 bool enum_dom_local_groups = False;
428
429 *num_entries = 0;
430
431 DEBUG(3,("ads: enum_dom_groups\n"));
432
433 if ( !winbindd_can_contact_domain( domain ) ) {
434 DEBUG(10,("enum_dom_groups: No incoming trust for domain %s\n",
435 domain->name));
436 return NT_STATUS_OK;
437 }
438
439 /* only grab domain local groups for our domain */
440 if ( domain->active_directory && strequal(lp_realm(), domain->alt_name) ) {
441 enum_dom_local_groups = True;
442 }
443
444 /* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o
445 * rollup-fixes:
446 *
447 * According to Section 5.1(4) of RFC 2251 if a value of a type is it's
448 * default value, it MUST be absent. In case of extensible matching the
449 * "dnattr" boolean defaults to FALSE and so it must be only be present
450 * when set to TRUE.
451 *
452 * When it is set to FALSE and the OpenLDAP lib (correctly) encodes a
453 * filter using bitwise matching rule then the buggy AD fails to decode
454 * the extensible match. As a workaround set it to TRUE and thereby add
455 * the dnAttributes "dn" field to cope with those older AD versions.
456 * It should not harm and won't put any additional load on the AD since
457 * none of the dn components have a bitmask-attribute.
458 *
459 * Thanks to Ralf Haferkamp for input and testing - Guenther */
460
461 filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))",
462 ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED,
463 ADS_LDAP_MATCHING_RULE_BIT_AND,
464 enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP);
465
466 if (filter == NULL) {
467 status = NT_STATUS_NO_MEMORY;
468 goto done;
469 }
470
471 ads = ads_cached_connection(domain);
472
473 if (!ads) {
474 domain->last_status = NT_STATUS_SERVER_DISABLED;
475 goto done;
476 }
477
478 rc = ads_search_retry(ads, &res, filter, attrs);
479 if (!ADS_ERR_OK(rc)) {
480 status = ads_ntstatus(rc);
481 DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
482 goto done;
483 } else if (!res) {
484 DEBUG(1,("enum_dom_groups ads_search returned NULL res\n"));
485 goto done;
486 }
487
488 count = ads_count_replies(ads, res);
489 if (count == 0) {
490 DEBUG(1,("enum_dom_groups: No groups found\n"));
491 goto done;
492 }
493
494 (*info) = talloc_zero_array(mem_ctx, struct wb_acct_info, count);
495 if (!*info) {
496 status = NT_STATUS_NO_MEMORY;
497 goto done;
498 }
499
500 i = 0;
501
502 for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
503 char *name, *gecos;
504 struct dom_sid sid;
505 uint32_t rid;
506
507 name = ads_pull_username(ads, (*info), msg);
508 gecos = ads_pull_string(ads, (*info), msg, "name");
509 if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
510 DEBUG(1,("No sid for %s !?\n", name));
511 continue;
512 }
513
514 if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
515 DEBUG(1,("No rid for %s !?\n", name));
516 continue;
517 }
518
519 (*info)[i].acct_name = name;
520 (*info)[i].acct_desc = gecos;
521 (*info)[i].rid = rid;
522 i++;
523 }
524
525 (*num_entries) = i;
526
527 status = NT_STATUS_OK;
528
529 DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));
530
531 done:
532 if (res)
533 ads_msgfree(ads, res);
534
535 return status;
536 }
537
538 /* list all domain local groups */
enum_local_groups(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t * num_entries,struct wb_acct_info ** info)539 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
540 TALLOC_CTX *mem_ctx,
541 uint32_t *num_entries,
542 struct wb_acct_info **info)
543 {
544 /*
545 * This is a stub function only as we returned the domain
546 * local groups in enum_dom_groups() if the domain->native field
547 * was true. This is a simple performance optimization when
548 * using LDAP.
549 *
550 * if we ever need to enumerate domain local groups separately,
551 * then this optimization in enum_dom_groups() will need
552 * to be split out
553 */
554 *num_entries = 0;
555
556 return NT_STATUS_OK;
557 }
558
559 /* convert a single name to a sid in a domain - use rpc methods */
name_to_sid(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const char * domain_name,const char * name,uint32_t flags,const char ** pdom_name,struct dom_sid * sid,enum lsa_SidType * type)560 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
561 TALLOC_CTX *mem_ctx,
562 const char *domain_name,
563 const char *name,
564 uint32_t flags,
565 const char **pdom_name,
566 struct dom_sid *sid,
567 enum lsa_SidType *type)
568 {
569 return msrpc_methods.name_to_sid(domain, mem_ctx, domain_name, name,
570 flags, pdom_name, sid, type);
571 }
572
573 /* convert a domain SID to a user or group name - use rpc methods */
sid_to_name(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const struct dom_sid * sid,char ** domain_name,char ** name,enum lsa_SidType * type)574 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
575 TALLOC_CTX *mem_ctx,
576 const struct dom_sid *sid,
577 char **domain_name,
578 char **name,
579 enum lsa_SidType *type)
580 {
581 return msrpc_methods.sid_to_name(domain, mem_ctx, sid,
582 domain_name, name, type);
583 }
584
585 /* convert a list of rids to names - use rpc methods */
rids_to_names(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const struct dom_sid * sid,uint32_t * rids,size_t num_rids,char ** domain_name,char *** names,enum lsa_SidType ** types)586 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
587 TALLOC_CTX *mem_ctx,
588 const struct dom_sid *sid,
589 uint32_t *rids,
590 size_t num_rids,
591 char **domain_name,
592 char ***names,
593 enum lsa_SidType **types)
594 {
595 return msrpc_methods.rids_to_names(domain, mem_ctx, sid,
596 rids, num_rids,
597 domain_name, names, types);
598 }
599
600 /* Lookup groups a user is a member of - alternate method, for when
601 tokenGroups are not available. */
lookup_usergroups_member(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const char * user_dn,struct dom_sid * primary_group,uint32_t * p_num_groups,struct dom_sid ** user_sids)602 static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
603 TALLOC_CTX *mem_ctx,
604 const char *user_dn,
605 struct dom_sid *primary_group,
606 uint32_t *p_num_groups, struct dom_sid **user_sids)
607 {
608 ADS_STATUS rc;
609 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
610 int count;
611 LDAPMessage *res = NULL;
612 LDAPMessage *msg = NULL;
613 char *ldap_exp;
614 ADS_STRUCT *ads;
615 const char *group_attrs[] = {"objectSid", NULL};
616 char *escaped_dn;
617 uint32_t num_groups = 0;
618
619 DEBUG(3,("ads: lookup_usergroups_member\n"));
620
621 if ( !winbindd_can_contact_domain( domain ) ) {
622 DEBUG(10,("lookup_usergroups_members: No incoming trust for domain %s\n",
623 domain->name));
624 return NT_STATUS_OK;
625 }
626
627 ads = ads_cached_connection(domain);
628
629 if (!ads) {
630 domain->last_status = NT_STATUS_SERVER_DISABLED;
631 goto done;
632 }
633
634 if (!(escaped_dn = escape_ldap_string(talloc_tos(), user_dn))) {
635 status = NT_STATUS_NO_MEMORY;
636 goto done;
637 }
638
639 ldap_exp = talloc_asprintf(mem_ctx,
640 "(&(member=%s)(objectCategory=group)(groupType:dn:%s:=%d))",
641 escaped_dn,
642 ADS_LDAP_MATCHING_RULE_BIT_AND,
643 GROUP_TYPE_SECURITY_ENABLED);
644 if (!ldap_exp) {
645 DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
646 TALLOC_FREE(escaped_dn);
647 status = NT_STATUS_NO_MEMORY;
648 goto done;
649 }
650
651 TALLOC_FREE(escaped_dn);
652
653 rc = ads_search_retry(ads, &res, ldap_exp, group_attrs);
654
655 if (!ADS_ERR_OK(rc)) {
656 DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
657 return ads_ntstatus(rc);
658 } else if (!res) {
659 DEBUG(1,("lookup_usergroups ads_search returned NULL res\n"));
660 return NT_STATUS_INTERNAL_ERROR;
661 }
662
663
664 count = ads_count_replies(ads, res);
665
666 *user_sids = NULL;
667 num_groups = 0;
668
669 /* always add the primary group to the sid array */
670 status = add_sid_to_array(mem_ctx, primary_group, user_sids,
671 &num_groups);
672 if (!NT_STATUS_IS_OK(status)) {
673 goto done;
674 }
675
676 if (count > 0) {
677 for (msg = ads_first_entry(ads, res); msg;
678 msg = ads_next_entry(ads, msg)) {
679 struct dom_sid group_sid;
680
681 if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) {
682 DEBUG(1,("No sid for this group ?!?\n"));
683 continue;
684 }
685
686 /* ignore Builtin groups from ADS - Guenther */
687 if (sid_check_is_in_builtin(&group_sid)) {
688 continue;
689 }
690
691 status = add_sid_to_array(mem_ctx, &group_sid,
692 user_sids, &num_groups);
693 if (!NT_STATUS_IS_OK(status)) {
694 goto done;
695 }
696 }
697
698 }
699
700 *p_num_groups = num_groups;
701 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
702
703 DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn));
704 done:
705 if (res)
706 ads_msgfree(ads, res);
707
708 return status;
709 }
710
711 /* Lookup groups a user is a member of - alternate method, for when
712 tokenGroups are not available. */
lookup_usergroups_memberof(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const char * user_dn,struct dom_sid * primary_group,uint32_t * p_num_groups,struct dom_sid ** user_sids)713 static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
714 TALLOC_CTX *mem_ctx,
715 const char *user_dn,
716 struct dom_sid *primary_group,
717 uint32_t *p_num_groups,
718 struct dom_sid **user_sids)
719 {
720 ADS_STATUS rc;
721 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
722 ADS_STRUCT *ads;
723 const char *attrs[] = {"memberOf", NULL};
724 uint32_t num_groups = 0;
725 struct dom_sid *group_sids = NULL;
726 size_t i;
727 char **strings = NULL;
728 size_t num_strings = 0, num_sids = 0;
729
730
731 DEBUG(3,("ads: lookup_usergroups_memberof\n"));
732
733 if ( !winbindd_can_contact_domain( domain ) ) {
734 DEBUG(10,("lookup_usergroups_memberof: No incoming trust for "
735 "domain %s\n", domain->name));
736 return NT_STATUS_OK;
737 }
738
739 ads = ads_cached_connection(domain);
740
741 if (!ads) {
742 domain->last_status = NT_STATUS_SERVER_DISABLED;
743 return NT_STATUS_UNSUCCESSFUL;
744 }
745
746 rc = ads_search_retry_extended_dn_ranged(ads, mem_ctx, user_dn, attrs,
747 ADS_EXTENDED_DN_HEX_STRING,
748 &strings, &num_strings);
749
750 if (!ADS_ERR_OK(rc)) {
751 DEBUG(1,("lookup_usergroups_memberof ads_search "
752 "member=%s: %s\n", user_dn, ads_errstr(rc)));
753 return ads_ntstatus(rc);
754 }
755
756 *user_sids = NULL;
757 num_groups = 0;
758
759 /* always add the primary group to the sid array */
760 status = add_sid_to_array(mem_ctx, primary_group, user_sids,
761 &num_groups);
762 if (!NT_STATUS_IS_OK(status)) {
763 goto done;
764 }
765
766 group_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_strings + 1);
767 if (!group_sids) {
768 status = NT_STATUS_NO_MEMORY;
769 goto done;
770 }
771
772 for (i=0; i<num_strings; i++) {
773 rc = ads_get_sid_from_extended_dn(mem_ctx, strings[i],
774 ADS_EXTENDED_DN_HEX_STRING,
775 &(group_sids)[i]);
776 if (!ADS_ERR_OK(rc)) {
777 /* ignore members without SIDs */
778 if (NT_STATUS_EQUAL(ads_ntstatus(rc),
779 NT_STATUS_NOT_FOUND)) {
780 continue;
781 }
782 else {
783 status = ads_ntstatus(rc);
784 goto done;
785 }
786 }
787 num_sids++;
788 }
789
790 if (i == 0) {
791 DEBUG(1,("No memberOf for this user?!?\n"));
792 status = NT_STATUS_NO_MEMORY;
793 goto done;
794 }
795
796 for (i=0; i<num_sids; i++) {
797
798 /* ignore Builtin groups from ADS - Guenther */
799 if (sid_check_is_in_builtin(&group_sids[i])) {
800 continue;
801 }
802
803 status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
804 &num_groups);
805 if (!NT_STATUS_IS_OK(status)) {
806 goto done;
807 }
808
809 }
810
811 *p_num_groups = num_groups;
812 status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
813
814 DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n",
815 user_dn));
816
817 done:
818 TALLOC_FREE(strings);
819 TALLOC_FREE(group_sids);
820
821 return status;
822 }
823
824
825 /* Lookup groups a user is a member of. */
lookup_usergroups(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const struct dom_sid * sid,uint32_t * p_num_groups,struct dom_sid ** user_sids)826 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
827 TALLOC_CTX *mem_ctx,
828 const struct dom_sid *sid,
829 uint32_t *p_num_groups, struct dom_sid **user_sids)
830 {
831 ADS_STRUCT *ads = NULL;
832 const char *attrs[] = {"tokenGroups", "primaryGroupID", NULL};
833 ADS_STATUS rc;
834 int count;
835 LDAPMessage *msg = NULL;
836 char *user_dn = NULL;
837 struct dom_sid *sids;
838 int i;
839 struct dom_sid primary_group;
840 uint32_t primary_group_rid;
841 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
842 uint32_t num_groups = 0;
843 struct dom_sid_buf buf;
844
845 DEBUG(3,("ads: lookup_usergroups\n"));
846 *p_num_groups = 0;
847
848 status = lookup_usergroups_cached(mem_ctx, sid,
849 p_num_groups, user_sids);
850 if (NT_STATUS_IS_OK(status)) {
851 return NT_STATUS_OK;
852 }
853
854 if ( !winbindd_can_contact_domain( domain ) ) {
855 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
856 domain->name));
857
858 /* Tell the cache manager not to remember this one */
859
860 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
861 }
862
863 ads = ads_cached_connection(domain);
864
865 if (!ads) {
866 domain->last_status = NT_STATUS_SERVER_DISABLED;
867 status = NT_STATUS_SERVER_DISABLED;
868 goto done;
869 }
870
871 rc = ads_search_retry_sid(ads, &msg, sid, attrs);
872
873 if (!ADS_ERR_OK(rc)) {
874 status = ads_ntstatus(rc);
875 DEBUG(1, ("lookup_usergroups(sid=%s) ads_search tokenGroups: "
876 "%s\n",
877 dom_sid_str_buf(sid, &buf),
878 ads_errstr(rc)));
879 goto done;
880 }
881
882 count = ads_count_replies(ads, msg);
883 if (count != 1) {
884 status = NT_STATUS_UNSUCCESSFUL;
885 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
886 "invalid number of results (count=%d)\n",
887 dom_sid_str_buf(sid, &buf),
888 count));
889 goto done;
890 }
891
892 if (!msg) {
893 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
894 dom_sid_str_buf(sid, &buf)));
895 status = NT_STATUS_UNSUCCESSFUL;
896 goto done;
897 }
898
899 user_dn = ads_get_dn(ads, mem_ctx, msg);
900 if (user_dn == NULL) {
901 status = NT_STATUS_NO_MEMORY;
902 goto done;
903 }
904
905 if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
906 DEBUG(1,("%s: No primary group for sid=%s !?\n",
907 domain->name,
908 dom_sid_str_buf(sid, &buf)));
909 goto done;
910 }
911
912 sid_compose(&primary_group, &domain->sid, primary_group_rid);
913
914 count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids);
915
916 /* there must always be at least one group in the token,
917 unless we are talking to a buggy Win2k server */
918
919 /* actually this only happens when the machine account has no read
920 * permissions on the tokenGroup attribute - gd */
921
922 if (count == 0) {
923
924 /* no tokenGroups */
925
926 /* lookup what groups this user is a member of by DN search on
927 * "memberOf" */
928
929 status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
930 &primary_group,
931 &num_groups, user_sids);
932 *p_num_groups = num_groups;
933 if (NT_STATUS_IS_OK(status)) {
934 goto done;
935 }
936
937 /* lookup what groups this user is a member of by DN search on
938 * "member" */
939
940 status = lookup_usergroups_member(domain, mem_ctx, user_dn,
941 &primary_group,
942 &num_groups, user_sids);
943 *p_num_groups = num_groups;
944 goto done;
945 }
946
947 *user_sids = NULL;
948 num_groups = 0;
949
950 status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
951 &num_groups);
952 if (!NT_STATUS_IS_OK(status)) {
953 goto done;
954 }
955
956 for (i=0;i<count;i++) {
957
958 /* ignore Builtin groups from ADS - Guenther */
959 if (sid_check_is_in_builtin(&sids[i])) {
960 continue;
961 }
962
963 status = add_sid_to_array_unique(mem_ctx, &sids[i],
964 user_sids, &num_groups);
965 if (!NT_STATUS_IS_OK(status)) {
966 goto done;
967 }
968 }
969
970 *p_num_groups = (uint32_t)num_groups;
971 status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
972
973 DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
974 dom_sid_str_buf(sid, &buf)));
975 done:
976 TALLOC_FREE(user_dn);
977 ads_msgfree(ads, msg);
978 return status;
979 }
980
981 /* Lookup aliases a user is member of - use rpc methods */
lookup_useraliases(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,uint32_t num_sids,const struct dom_sid * sids,uint32_t * num_aliases,uint32_t ** alias_rids)982 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
983 TALLOC_CTX *mem_ctx,
984 uint32_t num_sids, const struct dom_sid *sids,
985 uint32_t *num_aliases, uint32_t **alias_rids)
986 {
987 return msrpc_methods.lookup_useraliases(domain, mem_ctx, num_sids, sids,
988 num_aliases, alias_rids);
989 }
990
add_primary_group_members(ADS_STRUCT * ads,TALLOC_CTX * mem_ctx,uint32_t rid,char *** all_members,size_t * num_all_members)991 static NTSTATUS add_primary_group_members(
992 ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, uint32_t rid,
993 char ***all_members, size_t *num_all_members)
994 {
995 char *filter;
996 NTSTATUS status = NT_STATUS_NO_MEMORY;
997 ADS_STATUS rc;
998 const char *attrs[] = { "dn", NULL };
999 LDAPMessage *res = NULL;
1000 LDAPMessage *msg;
1001 char **members;
1002 size_t num_members;
1003 ads_control args;
1004
1005 filter = talloc_asprintf(
1006 mem_ctx, "(&(objectCategory=user)(primaryGroupID=%u))",
1007 (unsigned)rid);
1008 if (filter == NULL) {
1009 goto done;
1010 }
1011
1012 args.control = ADS_EXTENDED_DN_OID;
1013 args.val = ADS_EXTENDED_DN_HEX_STRING;
1014 args.critical = True;
1015
1016 rc = ads_do_search_all_args(ads, ads->config.bind_path,
1017 LDAP_SCOPE_SUBTREE, filter, attrs, &args,
1018 &res);
1019
1020 if (!ADS_ERR_OK(rc)) {
1021 status = ads_ntstatus(rc);
1022 DEBUG(1,("%s: ads_search: %s\n", __func__, ads_errstr(rc)));
1023 goto done;
1024 }
1025 if (res == NULL) {
1026 DEBUG(1,("%s: ads_search returned NULL res\n", __func__));
1027 goto done;
1028 }
1029
1030 num_members = ads_count_replies(ads, res);
1031
1032 DEBUG(10, ("%s: Got %ju primary group members\n", __func__,
1033 (uintmax_t)num_members));
1034
1035 if (num_members == 0) {
1036 status = NT_STATUS_OK;
1037 goto done;
1038 }
1039
1040 members = talloc_realloc(mem_ctx, *all_members, char *,
1041 *num_all_members + num_members);
1042 if (members == NULL) {
1043 DEBUG(1, ("%s: talloc_realloc failed\n", __func__));
1044 goto done;
1045 }
1046 *all_members = members;
1047
1048 for (msg = ads_first_entry(ads, res); msg != NULL;
1049 msg = ads_next_entry(ads, msg)) {
1050 char *dn;
1051
1052 dn = ads_get_dn(ads, members, msg);
1053 if (dn == NULL) {
1054 DEBUG(1, ("%s: ads_get_dn failed\n", __func__));
1055 continue;
1056 }
1057
1058 members[*num_all_members] = dn;
1059 *num_all_members += 1;
1060 }
1061
1062 status = NT_STATUS_OK;
1063 done:
1064 if (res != NULL) {
1065 ads_msgfree(ads, res);
1066 }
1067 TALLOC_FREE(filter);
1068 return status;
1069 }
1070
1071 /*
1072 find the members of a group, given a group rid and domain
1073 */
lookup_groupmem(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,const struct dom_sid * group_sid,enum lsa_SidType type,uint32_t * num_names,struct dom_sid ** sid_mem,char *** names,uint32_t ** name_types)1074 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
1075 TALLOC_CTX *mem_ctx,
1076 const struct dom_sid *group_sid,
1077 enum lsa_SidType type,
1078 uint32_t *num_names,
1079 struct dom_sid **sid_mem, char ***names,
1080 uint32_t **name_types)
1081 {
1082 ADS_STATUS rc;
1083 ADS_STRUCT *ads = NULL;
1084 char *ldap_exp;
1085 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1086 char *sidbinstr;
1087 char **members = NULL;
1088 size_t i;
1089 size_t num_members = 0;
1090 ads_control args;
1091 struct dom_sid *sid_mem_nocache = NULL;
1092 char **names_nocache = NULL;
1093 enum lsa_SidType *name_types_nocache = NULL;
1094 char **domains_nocache = NULL; /* only needed for rpccli_lsa_lookup_sids */
1095 uint32_t num_nocache = 0;
1096 TALLOC_CTX *tmp_ctx = NULL;
1097 uint32_t rid;
1098 struct dom_sid_buf buf;
1099
1100 DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name,
1101 dom_sid_str_buf(group_sid, &buf)));
1102
1103 *num_names = 0;
1104
1105 tmp_ctx = talloc_new(mem_ctx);
1106 if (!tmp_ctx) {
1107 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1108 status = NT_STATUS_NO_MEMORY;
1109 goto done;
1110 }
1111
1112 if (!sid_peek_rid(group_sid, &rid)) {
1113 DEBUG(1, ("%s: sid_peek_rid failed\n", __func__));
1114 status = NT_STATUS_INVALID_PARAMETER;
1115 goto done;
1116 }
1117
1118 if ( !winbindd_can_contact_domain( domain ) ) {
1119 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
1120 domain->name));
1121 return NT_STATUS_OK;
1122 }
1123
1124 ads = ads_cached_connection(domain);
1125
1126 if (!ads) {
1127 domain->last_status = NT_STATUS_SERVER_DISABLED;
1128 goto done;
1129 }
1130
1131 if ((sidbinstr = ldap_encode_ndr_dom_sid(talloc_tos(), group_sid)) == NULL) {
1132 status = NT_STATUS_NO_MEMORY;
1133 goto done;
1134 }
1135
1136 /* search for all members of the group */
1137 ldap_exp = talloc_asprintf(tmp_ctx, "(objectSid=%s)", sidbinstr);
1138 TALLOC_FREE(sidbinstr);
1139 if (ldap_exp == NULL) {
1140 DEBUG(1, ("ads: lookup_groupmem: talloc_asprintf for ldap_exp failed!\n"));
1141 status = NT_STATUS_NO_MEMORY;
1142 goto done;
1143 }
1144
1145 args.control = ADS_EXTENDED_DN_OID;
1146 args.val = ADS_EXTENDED_DN_HEX_STRING;
1147 args.critical = True;
1148
1149 rc = ads_ranged_search(ads, tmp_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path,
1150 ldap_exp, &args, "member", &members, &num_members);
1151
1152 if (!ADS_ERR_OK(rc)) {
1153 DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc)));
1154 status = NT_STATUS_UNSUCCESSFUL;
1155 goto done;
1156 }
1157
1158 DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members));
1159
1160 status = add_primary_group_members(ads, mem_ctx, rid,
1161 &members, &num_members);
1162 if (!NT_STATUS_IS_OK(status)) {
1163 DEBUG(10, ("%s: add_primary_group_members failed: %s\n",
1164 __func__, nt_errstr(status)));
1165 goto done;
1166 }
1167
1168 DEBUG(10, ("%s: Got %d sids after adding primary group members\n",
1169 __func__, (int)num_members));
1170
1171 /* Now that we have a list of sids, we need to get the
1172 * lists of names and name_types belonging to these sids.
1173 * even though conceptually not quite clean, we use the
1174 * RPC call lsa_lookup_sids for this since it can handle a
1175 * list of sids. ldap calls can just resolve one sid at a time.
1176 *
1177 * At this stage, the sids are still hidden in the exetended dn
1178 * member output format. We actually do a little better than
1179 * stated above: In extracting the sids from the member strings,
1180 * we try to resolve as many sids as possible from the
1181 * cache. Only the rest is passed to the lsa_lookup_sids call. */
1182
1183 if (num_members) {
1184 (*sid_mem) = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
1185 (*names) = talloc_zero_array(mem_ctx, char *, num_members);
1186 (*name_types) = talloc_zero_array(mem_ctx, uint32_t, num_members);
1187 (sid_mem_nocache) = talloc_zero_array(tmp_ctx, struct dom_sid, num_members);
1188
1189 if ((members == NULL) || (*sid_mem == NULL) ||
1190 (*names == NULL) || (*name_types == NULL) ||
1191 (sid_mem_nocache == NULL))
1192 {
1193 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
1194 status = NT_STATUS_NO_MEMORY;
1195 goto done;
1196 }
1197 }
1198 else {
1199 (*sid_mem) = NULL;
1200 (*names) = NULL;
1201 (*name_types) = NULL;
1202 }
1203
1204 for (i=0; i<num_members; i++) {
1205 enum lsa_SidType name_type;
1206 char *name, *domain_name;
1207 struct dom_sid sid;
1208
1209 rc = ads_get_sid_from_extended_dn(tmp_ctx, members[i], args.val,
1210 &sid);
1211 if (!ADS_ERR_OK(rc)) {
1212 if (NT_STATUS_EQUAL(ads_ntstatus(rc),
1213 NT_STATUS_NOT_FOUND)) {
1214 /* Group members can be objects, like Exchange
1215 * Public Folders, that don't have a SID. Skip
1216 * them. */
1217 continue;
1218 }
1219 else {
1220 status = ads_ntstatus(rc);
1221 goto done;
1222 }
1223 }
1224 if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name,
1225 &name_type)) {
1226 DEBUG(10,("ads: lookup_groupmem: got sid %s from "
1227 "cache\n",
1228 dom_sid_str_buf(&sid, &buf)));
1229 sid_copy(&(*sid_mem)[*num_names], &sid);
1230 (*names)[*num_names] = fill_domain_username_talloc(
1231 *names,
1232 domain_name,
1233 name,
1234 true);
1235
1236 (*name_types)[*num_names] = name_type;
1237 (*num_names)++;
1238 }
1239 else {
1240 DEBUG(10, ("ads: lookup_groupmem: sid %s not found in "
1241 "cache\n",
1242 dom_sid_str_buf(&sid, &buf)));
1243 sid_copy(&(sid_mem_nocache)[num_nocache], &sid);
1244 num_nocache++;
1245 }
1246 }
1247
1248 DEBUG(10, ("ads: lookup_groupmem: %d sids found in cache, "
1249 "%d left for lsa_lookupsids\n", *num_names, num_nocache));
1250
1251 /* handle sids not resolved from cache by lsa_lookup_sids */
1252 if (num_nocache > 0) {
1253
1254 status = winbindd_lookup_sids(tmp_ctx,
1255 domain,
1256 num_nocache,
1257 sid_mem_nocache,
1258 &domains_nocache,
1259 &names_nocache,
1260 &name_types_nocache);
1261
1262 if (!(NT_STATUS_IS_OK(status) ||
1263 NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED) ||
1264 NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)))
1265 {
1266 DEBUG(1, ("lsa_lookupsids call failed with %s "
1267 "- retrying...\n", nt_errstr(status)));
1268
1269 status = winbindd_lookup_sids(tmp_ctx,
1270 domain,
1271 num_nocache,
1272 sid_mem_nocache,
1273 &domains_nocache,
1274 &names_nocache,
1275 &name_types_nocache);
1276 }
1277
1278 if (NT_STATUS_IS_OK(status) ||
1279 NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED))
1280 {
1281 /* Copy the entries over from the "_nocache" arrays
1282 * to the result arrays, skipping the gaps the
1283 * lookup_sids call left. */
1284 for (i=0; i < num_nocache; i++) {
1285 if (((names_nocache)[i] != NULL) &&
1286 ((name_types_nocache)[i] != SID_NAME_UNKNOWN))
1287 {
1288 sid_copy(&(*sid_mem)[*num_names],
1289 &sid_mem_nocache[i]);
1290 (*names)[*num_names] =
1291 fill_domain_username_talloc(
1292 *names,
1293 domains_nocache[i],
1294 names_nocache[i],
1295 true);
1296 (*name_types)[*num_names] = name_types_nocache[i];
1297 (*num_names)++;
1298 }
1299 }
1300 }
1301 else if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1302 DEBUG(10, ("lookup_groupmem: lsa_lookup_sids could "
1303 "not map any SIDs at all.\n"));
1304 /* Don't handle this as an error here.
1305 * There is nothing left to do with respect to the
1306 * overall result... */
1307 }
1308 else if (!NT_STATUS_IS_OK(status)) {
1309 DEBUG(10, ("lookup_groupmem: Error looking up %d "
1310 "sids via rpc_lsa_lookup_sids: %s\n",
1311 (int)num_members, nt_errstr(status)));
1312 goto done;
1313 }
1314 }
1315
1316 status = NT_STATUS_OK;
1317 DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n",
1318 dom_sid_str_buf(group_sid, &buf)));
1319
1320 done:
1321
1322 TALLOC_FREE(tmp_ctx);
1323
1324 return status;
1325 }
1326
1327 /* find the sequence number for a domain */
sequence_number(struct winbindd_domain * domain,uint32_t * seq)1328 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32_t *seq)
1329 {
1330 ADS_STRUCT *ads = NULL;
1331 ADS_STATUS rc;
1332
1333 DEBUG(3,("ads: fetch sequence_number for %s\n", domain->name));
1334
1335 if ( !winbindd_can_contact_domain( domain ) ) {
1336 DEBUG(10,("sequence: No incoming trust for domain %s\n",
1337 domain->name));
1338 *seq = time(NULL);
1339 return NT_STATUS_OK;
1340 }
1341
1342 if (IS_AD_DC) {
1343 DEBUG(10,("sequence: Avoid LDAP connection for domain %s\n",
1344 domain->name));
1345 *seq = time(NULL);
1346 return NT_STATUS_OK;
1347 }
1348
1349 *seq = DOM_SEQUENCE_NONE;
1350
1351 ads = ads_cached_connection(domain);
1352
1353 if (!ads) {
1354 domain->last_status = NT_STATUS_SERVER_DISABLED;
1355 return NT_STATUS_UNSUCCESSFUL;
1356 }
1357
1358 rc = ads_USN(ads, seq);
1359
1360 if (!ADS_ERR_OK(rc)) {
1361
1362 /* its a dead connection, destroy it */
1363
1364 if (domain->private_data) {
1365 ads = (ADS_STRUCT *)domain->private_data;
1366 ads->is_mine = True;
1367 ads_destroy(&ads);
1368 ads_kdestroy(WINBIND_CCACHE_NAME);
1369 domain->private_data = NULL;
1370 }
1371 }
1372 return ads_ntstatus(rc);
1373 }
1374
1375 /* find the lockout policy of a domain - use rpc methods */
lockout_policy(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,struct samr_DomInfo12 * policy)1376 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
1377 TALLOC_CTX *mem_ctx,
1378 struct samr_DomInfo12 *policy)
1379 {
1380 return msrpc_methods.lockout_policy(domain, mem_ctx, policy);
1381 }
1382
1383 /* find the password policy of a domain - use rpc methods */
password_policy(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,struct samr_DomInfo1 * policy)1384 static NTSTATUS password_policy(struct winbindd_domain *domain,
1385 TALLOC_CTX *mem_ctx,
1386 struct samr_DomInfo1 *policy)
1387 {
1388 return msrpc_methods.password_policy(domain, mem_ctx, policy);
1389 }
1390
1391 /* get a list of trusted domains */
trusted_domains(struct winbindd_domain * domain,TALLOC_CTX * mem_ctx,struct netr_DomainTrustList * trusts)1392 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1393 TALLOC_CTX *mem_ctx,
1394 struct netr_DomainTrustList *trusts)
1395 {
1396 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1397 WERROR werr;
1398 uint32_t i;
1399 uint32_t flags;
1400 struct rpc_pipe_client *cli;
1401 int ret_count;
1402 struct dcerpc_binding_handle *b;
1403
1404 DEBUG(3,("ads: trusted_domains\n"));
1405
1406 ZERO_STRUCTP(trusts);
1407
1408 /* If this is our primary domain or a root in our forest,
1409 query for all trusts. If not, then just look for domain
1410 trusts in the target forest */
1411
1412 if (domain->primary || domain_is_forest_root(domain)) {
1413 flags = NETR_TRUST_FLAG_OUTBOUND |
1414 NETR_TRUST_FLAG_INBOUND |
1415 NETR_TRUST_FLAG_IN_FOREST;
1416 } else {
1417 flags = NETR_TRUST_FLAG_IN_FOREST;
1418 }
1419
1420 result = cm_connect_netlogon(domain, &cli);
1421
1422 if (!NT_STATUS_IS_OK(result)) {
1423 DEBUG(5, ("trusted_domains: Could not open a connection to %s "
1424 "for PIPE_NETLOGON (%s)\n",
1425 domain->name, nt_errstr(result)));
1426 return NT_STATUS_UNSUCCESSFUL;
1427 }
1428
1429 b = cli->binding_handle;
1430
1431 result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
1432 cli->desthost,
1433 flags,
1434 trusts,
1435 &werr);
1436 if (!NT_STATUS_IS_OK(result)) {
1437 return result;
1438 }
1439
1440 if (!W_ERROR_IS_OK(werr)) {
1441 return werror_to_ntstatus(werr);
1442 }
1443 if (trusts->count == 0) {
1444 return NT_STATUS_OK;
1445 }
1446
1447 /* Copy across names and sids */
1448
1449 ret_count = 0;
1450 for (i = 0; i < trusts->count; i++) {
1451 struct netr_DomainTrust *trust = &trusts->array[i];
1452 struct winbindd_domain d;
1453
1454 ZERO_STRUCT(d);
1455
1456 /*
1457 * drop external trusts if this is not our primary
1458 * domain. This means that the returned number of
1459 * domains may be less that the ones actually trusted
1460 * by the DC.
1461 */
1462
1463 if ((trust->trust_attributes
1464 & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
1465 !domain->primary )
1466 {
1467 DEBUG(10,("trusted_domains: Skipping external trusted "
1468 "domain %s because it is outside of our "
1469 "primary domain\n",
1470 trust->netbios_name));
1471 continue;
1472 }
1473
1474 /* add to the trusted domain cache */
1475
1476 d.name = discard_const_p(char, trust->netbios_name);
1477 d.alt_name = discard_const_p(char, trust->dns_name);
1478
1479 if (trust->sid) {
1480 sid_copy(&d.sid, trust->sid);
1481 } else {
1482 sid_copy(&d.sid, &global_sid_NULL);
1483 }
1484
1485 if ( domain->primary ) {
1486 DEBUG(10,("trusted_domains(ads): Searching "
1487 "trusted domain list of %s and storing "
1488 "trust flags for domain %s\n",
1489 domain->name, d.alt_name));
1490
1491 d.domain_flags = trust->trust_flags;
1492 d.domain_type = trust->trust_type;
1493 d.domain_trust_attribs = trust->trust_attributes;
1494
1495 wcache_tdc_add_domain( &d );
1496 ret_count++;
1497 } else if (domain_is_forest_root(domain)) {
1498 /* Check if we already have this record. If
1499 * we are following our forest root that is not
1500 * our primary domain, we want to keep trust
1501 * flags from the perspective of our primary
1502 * domain not our forest root. */
1503 struct winbindd_tdc_domain *exist = NULL;
1504
1505 exist = wcache_tdc_fetch_domain(
1506 talloc_tos(), trust->netbios_name);
1507 if (!exist) {
1508 DEBUG(10,("trusted_domains(ads): Searching "
1509 "trusted domain list of %s and "
1510 "storing trust flags for domain "
1511 "%s\n", domain->name, d.alt_name));
1512 d.domain_flags = trust->trust_flags;
1513 d.domain_type = trust->trust_type;
1514 d.domain_trust_attribs =
1515 trust->trust_attributes;
1516
1517 wcache_tdc_add_domain( &d );
1518 ret_count++;
1519 }
1520 TALLOC_FREE(exist);
1521 } else {
1522 /* This gets a little tricky. If we are
1523 following a transitive forest trust, then
1524 innerit the flags, type, and attribs from
1525 the domain we queried to make sure we don't
1526 record the view of the trust from the wrong
1527 side. Always view it from the side of our
1528 primary domain. --jerry */
1529 struct winbindd_tdc_domain *parent = NULL;
1530
1531 DEBUG(10,("trusted_domains(ads): Searching "
1532 "trusted domain list of %s and inheriting "
1533 "trust flags for domain %s\n",
1534 domain->name, d.alt_name));
1535
1536 parent = wcache_tdc_fetch_domain(talloc_tos(),
1537 domain->name);
1538 if (parent) {
1539 d.domain_flags = parent->trust_flags;
1540 d.domain_type = parent->trust_type;
1541 d.domain_trust_attribs = parent->trust_attribs;
1542 } else {
1543 d.domain_flags = domain->domain_flags;
1544 d.domain_type = domain->domain_type;
1545 d.domain_trust_attribs =
1546 domain->domain_trust_attribs;
1547 }
1548 TALLOC_FREE(parent);
1549
1550 /*
1551 * We need to pass the modified properties
1552 * to the caller.
1553 */
1554 trust->trust_flags = d.domain_flags;
1555 trust->trust_type = d.domain_type;
1556 trust->trust_attributes = d.domain_trust_attribs;
1557
1558 wcache_tdc_add_domain( &d );
1559 ret_count++;
1560 }
1561 }
1562 return result;
1563 }
1564
1565 /* the ADS backend methods are exposed via this structure */
1566 struct winbindd_methods ads_methods = {
1567 True,
1568 query_user_list,
1569 enum_dom_groups,
1570 enum_local_groups,
1571 name_to_sid,
1572 sid_to_name,
1573 rids_to_names,
1574 lookup_usergroups,
1575 lookup_useraliases,
1576 lookup_groupmem,
1577 sequence_number,
1578 lockout_policy,
1579 password_policy,
1580 trusted_domains,
1581 };
1582
1583 #endif
1584