source: branches/samba-3.5.x/source3/winbindd/winbindd_rpc.c

Last change on this file was 596, checked in by Herwig Bauernfeind, 14 years ago

Samba 3.5: Update trunk to 3.5.8

File size: 34.2 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Winbind rpc backend functions
5
6 Copyright (C) Tim Potter 2000-2001,2003
7 Copyright (C) Andrew Tridgell 2001
8 Copyright (C) Volker Lendecke 2005
9 Copyright (C) Guenther Deschner 2008 (pidl conversion)
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#include "includes.h"
26#include "winbindd.h"
27#include "../librpc/gen_ndr/cli_samr.h"
28#include "../librpc/gen_ndr/cli_lsa.h"
29
30#undef DBGC_CLASS
31#define DBGC_CLASS DBGC_WINBIND
32
33
34/* Query display info for a domain. This returns enough information plus a
35 bit extra to give an overview of domain users for the User Manager
36 application. */
37static NTSTATUS query_user_list(struct winbindd_domain *domain,
38 TALLOC_CTX *mem_ctx,
39 uint32 *num_entries,
40 struct wbint_userinfo **info)
41{
42 NTSTATUS result;
43 struct policy_handle dom_pol;
44 unsigned int i, start_idx;
45 uint32 loop_count;
46 struct rpc_pipe_client *cli;
47
48 DEBUG(3,("rpc: query_user_list\n"));
49
50 *num_entries = 0;
51 *info = NULL;
52
53 if ( !winbindd_can_contact_domain( domain ) ) {
54 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
55 domain->name));
56 return NT_STATUS_OK;
57 }
58
59 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
60 if (!NT_STATUS_IS_OK(result))
61 return result;
62
63 i = start_idx = 0;
64 loop_count = 0;
65
66 do {
67 uint32 num_dom_users, j;
68 uint32 max_entries, max_size;
69 uint32_t total_size, returned_size;
70
71 union samr_DispInfo disp_info;
72
73 /* this next bit is copied from net_user_list_internal() */
74
75 get_query_dispinfo_params(loop_count, &max_entries,
76 &max_size);
77
78 result = rpccli_samr_QueryDisplayInfo(cli, mem_ctx,
79 &dom_pol,
80 1,
81 start_idx,
82 max_entries,
83 max_size,
84 &total_size,
85 &returned_size,
86 &disp_info);
87
88 if (!NT_STATUS_IS_OK(result)) {
89 if (!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
90 return result;
91 }
92 }
93
94 num_dom_users = disp_info.info1.count;
95 start_idx += disp_info.info1.count;
96 loop_count++;
97
98 *num_entries += num_dom_users;
99
100 *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
101 struct wbint_userinfo,
102 *num_entries);
103
104 if (!(*info)) {
105 return NT_STATUS_NO_MEMORY;
106 }
107
108 for (j = 0; j < num_dom_users; i++, j++) {
109
110 uint32_t rid = disp_info.info1.entries[j].rid;
111
112 (*info)[i].acct_name = talloc_strdup(mem_ctx,
113 disp_info.info1.entries[j].account_name.string);
114 (*info)[i].full_name = talloc_strdup(mem_ctx,
115 disp_info.info1.entries[j].full_name.string);
116 (*info)[i].homedir = NULL;
117 (*info)[i].shell = NULL;
118 sid_compose(&(*info)[i].user_sid, &domain->sid, rid);
119
120 /* For the moment we set the primary group for
121 every user to be the Domain Users group.
122 There are serious problems with determining
123 the actual primary group for large domains.
124 This should really be made into a 'winbind
125 force group' smb.conf parameter or
126 something like that. */
127
128 sid_compose(&(*info)[i].group_sid, &domain->sid,
129 DOMAIN_GROUP_RID_USERS);
130 }
131
132 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
133
134 return result;
135}
136
137/* list all domain groups */
138static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
139 TALLOC_CTX *mem_ctx,
140 uint32 *num_entries,
141 struct acct_info **info)
142{
143 struct policy_handle dom_pol;
144 NTSTATUS status;
145 uint32 start = 0;
146 struct rpc_pipe_client *cli;
147
148 *num_entries = 0;
149 *info = NULL;
150
151 DEBUG(3,("rpc: enum_dom_groups\n"));
152
153 if ( !winbindd_can_contact_domain( domain ) ) {
154 DEBUG(10,("enum_domain_groups: No incoming trust for domain %s\n",
155 domain->name));
156 return NT_STATUS_OK;
157 }
158
159 status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
160 if (!NT_STATUS_IS_OK(status))
161 return status;
162
163 do {
164 struct samr_SamArray *sam_array = NULL;
165 uint32 count = 0;
166 TALLOC_CTX *mem_ctx2;
167 int g;
168
169 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
170
171 /* start is updated by this call. */
172 status = rpccli_samr_EnumDomainGroups(cli, mem_ctx2,
173 &dom_pol,
174 &start,
175 &sam_array,
176 0xFFFF, /* buffer size? */
177 &count);
178
179 if (!NT_STATUS_IS_OK(status) &&
180 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
181 talloc_destroy(mem_ctx2);
182 break;
183 }
184
185 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
186 struct acct_info,
187 (*num_entries) + count);
188 if (! *info) {
189 talloc_destroy(mem_ctx2);
190 return NT_STATUS_NO_MEMORY;
191 }
192
193 for (g=0; g < count; g++) {
194
195 fstrcpy((*info)[*num_entries + g].acct_name,
196 sam_array->entries[g].name.string);
197 (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
198 }
199
200 (*num_entries) += count;
201 talloc_destroy(mem_ctx2);
202 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
203
204 return status;
205}
206
207/* List all domain groups */
208
209static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
210 TALLOC_CTX *mem_ctx,
211 uint32 *num_entries,
212 struct acct_info **info)
213{
214 struct policy_handle dom_pol;
215 NTSTATUS result;
216 struct rpc_pipe_client *cli;
217
218 *num_entries = 0;
219 *info = NULL;
220
221 DEBUG(3,("rpc: enum_local_groups\n"));
222
223 if ( !winbindd_can_contact_domain( domain ) ) {
224 DEBUG(10,("enum_local_groups: No incoming trust for domain %s\n",
225 domain->name));
226 return NT_STATUS_OK;
227 }
228
229 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
230 if (!NT_STATUS_IS_OK(result))
231 return result;
232
233 do {
234 struct samr_SamArray *sam_array = NULL;
235 uint32 count = 0, start = *num_entries;
236 TALLOC_CTX *mem_ctx2;
237 int g;
238
239 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
240
241 result = rpccli_samr_EnumDomainAliases(cli, mem_ctx2,
242 &dom_pol,
243 &start,
244 &sam_array,
245 0xFFFF, /* buffer size? */
246 &count);
247 if (!NT_STATUS_IS_OK(result) &&
248 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
249 {
250 talloc_destroy(mem_ctx2);
251 return result;
252 }
253
254 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
255 struct acct_info,
256 (*num_entries) + count);
257 if (! *info) {
258 talloc_destroy(mem_ctx2);
259 return NT_STATUS_NO_MEMORY;
260 }
261
262 for (g=0; g < count; g++) {
263
264 fstrcpy((*info)[*num_entries + g].acct_name,
265 sam_array->entries[g].name.string);
266 (*info)[*num_entries + g].rid = sam_array->entries[g].idx;
267 }
268
269 (*num_entries) += count;
270 talloc_destroy(mem_ctx2);
271
272 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
273
274 return result;
275}
276
277/* convert a single name to a sid in a domain */
278static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
279 TALLOC_CTX *mem_ctx,
280 const char *domain_name,
281 const char *name,
282 uint32_t flags,
283 DOM_SID *sid,
284 enum lsa_SidType *type)
285{
286 NTSTATUS result;
287 DOM_SID *sids = NULL;
288 enum lsa_SidType *types = NULL;
289 char *full_name = NULL;
290 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
291 char *mapped_name = NULL;
292
293 if (name == NULL || *name=='\0') {
294 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
295 } else if (domain_name == NULL || *domain_name == '\0') {
296 full_name = talloc_asprintf(mem_ctx, "%s", name);
297 } else {
298 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
299 }
300 if (!full_name) {
301 DEBUG(0, ("talloc_asprintf failed!\n"));
302 return NT_STATUS_NO_MEMORY;
303 }
304
305 DEBUG(3,("rpc: name_to_sid name=%s\n", full_name));
306
307 name_map_status = normalize_name_unmap(mem_ctx, full_name,
308 &mapped_name);
309
310 /* Reset the full_name pointer if we mapped anytthing */
311
312 if (NT_STATUS_IS_OK(name_map_status) ||
313 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
314 {
315 full_name = mapped_name;
316 }
317
318 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n",
319 full_name?full_name:"", domain_name ));
320
321 result = winbindd_lookup_names(mem_ctx, domain, 1,
322 (const char **)&full_name, NULL,
323 &sids, &types);
324 if (!NT_STATUS_IS_OK(result))
325 return result;
326
327 /* Return rid and type if lookup successful */
328
329 sid_copy(sid, &sids[0]);
330 *type = types[0];
331
332 return NT_STATUS_OK;
333}
334
335/*
336 convert a domain SID to a user or group name
337*/
338static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
339 TALLOC_CTX *mem_ctx,
340 const DOM_SID *sid,
341 char **domain_name,
342 char **name,
343 enum lsa_SidType *type)
344{
345 char **domains;
346 char **names;
347 enum lsa_SidType *types = NULL;
348 NTSTATUS result;
349 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
350 char *mapped_name = NULL;
351
352 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_dbg(sid),
353 domain->name ));
354
355 result = winbindd_lookup_sids(mem_ctx,
356 domain,
357 1,
358 sid,
359 &domains,
360 &names,
361 &types);
362 if (!NT_STATUS_IS_OK(result)) {
363 DEBUG(2,("msrpc_sid_to_name: failed to lookup sids: %s\n",
364 nt_errstr(result)));
365 return result;
366 }
367
368
369 *type = (enum lsa_SidType)types[0];
370 *domain_name = domains[0];
371 *name = names[0];
372
373 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
374
375 name_map_status = normalize_name_map(mem_ctx, domain, *name,
376 &mapped_name);
377 if (NT_STATUS_IS_OK(name_map_status) ||
378 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
379 {
380 *name = mapped_name;
381 DEBUG(5,("returning mapped name -- %s\n", *name));
382 }
383
384 return NT_STATUS_OK;
385}
386
387static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
388 TALLOC_CTX *mem_ctx,
389 const DOM_SID *sid,
390 uint32 *rids,
391 size_t num_rids,
392 char **domain_name,
393 char ***names,
394 enum lsa_SidType **types)
395{
396 char **domains;
397 NTSTATUS result;
398 DOM_SID *sids;
399 size_t i;
400 char **ret_names;
401
402 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
403
404 if (num_rids) {
405 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
406 if (sids == NULL) {
407 return NT_STATUS_NO_MEMORY;
408 }
409 } else {
410 sids = NULL;
411 }
412
413 for (i=0; i<num_rids; i++) {
414 if (!sid_compose(&sids[i], sid, rids[i])) {
415 return NT_STATUS_INTERNAL_ERROR;
416 }
417 }
418
419 result = winbindd_lookup_sids(mem_ctx,
420 domain,
421 num_rids,
422 sids,
423 &domains,
424 names,
425 types);
426
427 if (!NT_STATUS_IS_OK(result) &&
428 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
429 return result;
430 }
431
432 ret_names = *names;
433 for (i=0; i<num_rids; i++) {
434 NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
435 char *mapped_name = NULL;
436
437 if ((*types)[i] != SID_NAME_UNKNOWN) {
438 name_map_status = normalize_name_map(mem_ctx,
439 domain,
440 ret_names[i],
441 &mapped_name);
442 if (NT_STATUS_IS_OK(name_map_status) ||
443 NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
444 {
445 ret_names[i] = mapped_name;
446 }
447
448 *domain_name = domains[i];
449 }
450 }
451
452 return result;
453}
454
455/* Lookup user information from a rid or username. */
456static NTSTATUS query_user(struct winbindd_domain *domain,
457 TALLOC_CTX *mem_ctx,
458 const DOM_SID *user_sid,
459 struct wbint_userinfo *user_info)
460{
461 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
462 struct policy_handle dom_pol, user_pol;
463 union samr_UserInfo *info = NULL;
464 uint32 user_rid;
465 struct netr_SamInfo3 *user;
466 struct rpc_pipe_client *cli;
467
468 DEBUG(3,("rpc: query_user sid=%s\n", sid_string_dbg(user_sid)));
469
470 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
471 return NT_STATUS_UNSUCCESSFUL;
472
473 user_info->homedir = NULL;
474 user_info->shell = NULL;
475 user_info->primary_gid = (gid_t)-1;
476
477 /* try netsamlogon cache first */
478
479 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
480 {
481
482 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
483 sid_string_dbg(user_sid)));
484
485 sid_compose(&user_info->user_sid, &domain->sid, user->base.rid);
486 sid_compose(&user_info->group_sid, &domain->sid,
487 user->base.primary_gid);
488
489 user_info->acct_name = talloc_strdup(mem_ctx,
490 user->base.account_name.string);
491 user_info->full_name = talloc_strdup(mem_ctx,
492 user->base.full_name.string);
493
494 TALLOC_FREE(user);
495
496 return NT_STATUS_OK;
497 }
498
499 if ( !winbindd_can_contact_domain( domain ) ) {
500 DEBUG(10,("query_user: No incoming trust for domain %s\n",
501 domain->name));
502 return NT_STATUS_OK;
503 }
504
505 /* no cache; hit the wire */
506
507 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
508 if (!NT_STATUS_IS_OK(result))
509 return result;
510
511 /* Get user handle */
512 result = rpccli_samr_OpenUser(cli, mem_ctx,
513 &dom_pol,
514 SEC_FLAG_MAXIMUM_ALLOWED,
515 user_rid,
516 &user_pol);
517
518 if (!NT_STATUS_IS_OK(result))
519 return result;
520
521 /* Get user info */
522 result = rpccli_samr_QueryUserInfo(cli, mem_ctx,
523 &user_pol,
524 0x15,
525 &info);
526
527 rpccli_samr_Close(cli, mem_ctx, &user_pol);
528
529 if (!NT_STATUS_IS_OK(result))
530 return result;
531
532 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
533 sid_compose(&user_info->group_sid, &domain->sid,
534 info->info21.primary_gid);
535 user_info->acct_name = talloc_strdup(mem_ctx,
536 info->info21.account_name.string);
537 user_info->full_name = talloc_strdup(mem_ctx,
538 info->info21.full_name.string);
539 user_info->homedir = NULL;
540 user_info->shell = NULL;
541 user_info->primary_gid = (gid_t)-1;
542
543 return NT_STATUS_OK;
544}
545
546/* Lookup groups a user is a member of. I wish Unix had a call like this! */
547static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
548 TALLOC_CTX *mem_ctx,
549 const DOM_SID *user_sid,
550 uint32 *num_groups, DOM_SID **user_grpsids)
551{
552 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
553 struct policy_handle dom_pol, user_pol;
554 uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
555 struct samr_RidWithAttributeArray *rid_array = NULL;
556 unsigned int i;
557 uint32 user_rid;
558 struct rpc_pipe_client *cli;
559
560 DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_string_dbg(user_sid)));
561
562 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
563 return NT_STATUS_UNSUCCESSFUL;
564
565 *num_groups = 0;
566 *user_grpsids = NULL;
567
568 /* so lets see if we have a cached user_info_3 */
569 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
570 num_groups, user_grpsids);
571
572 if (NT_STATUS_IS_OK(result)) {
573 return NT_STATUS_OK;
574 }
575
576 if ( !winbindd_can_contact_domain( domain ) ) {
577 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
578 domain->name));
579
580 /* Tell the cache manager not to remember this one */
581
582 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
583 }
584
585 /* no cache; hit the wire */
586
587 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
588 if (!NT_STATUS_IS_OK(result))
589 return result;
590
591 /* Get user handle */
592 result = rpccli_samr_OpenUser(cli, mem_ctx,
593 &dom_pol,
594 des_access,
595 user_rid,
596 &user_pol);
597
598 if (!NT_STATUS_IS_OK(result))
599 return result;
600
601 /* Query user rids */
602 result = rpccli_samr_GetGroupsForUser(cli, mem_ctx,
603 &user_pol,
604 &rid_array);
605 *num_groups = rid_array->count;
606
607 rpccli_samr_Close(cli, mem_ctx, &user_pol);
608
609 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
610 return result;
611
612 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
613 if (!(*user_grpsids))
614 return NT_STATUS_NO_MEMORY;
615
616 for (i=0;i<(*num_groups);i++) {
617 sid_copy(&((*user_grpsids)[i]), &domain->sid);
618 sid_append_rid(&((*user_grpsids)[i]),
619 rid_array->rids[i].rid);
620 }
621
622 return NT_STATUS_OK;
623}
624
625#define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
626
627static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
628 TALLOC_CTX *mem_ctx,
629 uint32 num_sids, const DOM_SID *sids,
630 uint32 *num_aliases,
631 uint32 **alias_rids)
632{
633 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
634 struct policy_handle dom_pol;
635 uint32 num_query_sids = 0;
636 int i;
637 struct rpc_pipe_client *cli;
638 struct samr_Ids alias_rids_query;
639 int rangesize = MAX_SAM_ENTRIES_W2K;
640 uint32 total_sids = 0;
641 int num_queries = 1;
642
643 *num_aliases = 0;
644 *alias_rids = NULL;
645
646 DEBUG(3,("rpc: lookup_useraliases\n"));
647
648 if ( !winbindd_can_contact_domain( domain ) ) {
649 DEBUG(10,("msrpc_lookup_useraliases: No incoming trust for domain %s\n",
650 domain->name));
651 return NT_STATUS_OK;
652 }
653
654 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
655 if (!NT_STATUS_IS_OK(result))
656 return result;
657
658 do {
659 /* prepare query */
660 struct lsa_SidArray sid_array;
661
662 ZERO_STRUCT(sid_array);
663
664 num_query_sids = MIN(num_sids - total_sids, rangesize);
665
666 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
667 num_queries, num_query_sids));
668
669 if (num_query_sids) {
670 sid_array.sids = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_SidPtr, num_query_sids);
671 if (sid_array.sids == NULL) {
672 return NT_STATUS_NO_MEMORY;
673 }
674 } else {
675 sid_array.sids = NULL;
676 }
677
678 for (i=0; i<num_query_sids; i++) {
679 sid_array.sids[i].sid = sid_dup_talloc(mem_ctx, &sids[total_sids++]);
680 if (!sid_array.sids[i].sid) {
681 TALLOC_FREE(sid_array.sids);
682 return NT_STATUS_NO_MEMORY;
683 }
684 }
685 sid_array.num_sids = num_query_sids;
686
687 /* do request */
688 result = rpccli_samr_GetAliasMembership(cli, mem_ctx,
689 &dom_pol,
690 &sid_array,
691 &alias_rids_query);
692
693 if (!NT_STATUS_IS_OK(result)) {
694 *num_aliases = 0;
695 *alias_rids = NULL;
696 TALLOC_FREE(sid_array.sids);
697 goto done;
698 }
699
700 /* process output */
701
702 for (i=0; i<alias_rids_query.count; i++) {
703 size_t na = *num_aliases;
704 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query.ids[i],
705 alias_rids, &na)) {
706 return NT_STATUS_NO_MEMORY;
707 }
708 *num_aliases = na;
709 }
710
711 TALLOC_FREE(sid_array.sids);
712
713 num_queries++;
714
715 } while (total_sids < num_sids);
716
717 done:
718 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
719 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
720
721 return result;
722}
723
724
725/* Lookup group membership given a rid. */
726static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
727 TALLOC_CTX *mem_ctx,
728 const DOM_SID *group_sid,
729 enum lsa_SidType type,
730 uint32 *num_names,
731 DOM_SID **sid_mem, char ***names,
732 uint32 **name_types)
733{
734 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
735 uint32 i, total_names = 0;
736 struct policy_handle dom_pol, group_pol;
737 uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
738 uint32 *rid_mem = NULL;
739 uint32 group_rid;
740 unsigned int j, r;
741 struct rpc_pipe_client *cli;
742 unsigned int orig_timeout;
743 struct samr_RidTypeArray *rids = NULL;
744
745 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
746 sid_string_dbg(group_sid)));
747
748 if ( !winbindd_can_contact_domain( domain ) ) {
749 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
750 domain->name));
751 return NT_STATUS_OK;
752 }
753
754 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
755 return NT_STATUS_UNSUCCESSFUL;
756
757 *num_names = 0;
758
759 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
760 if (!NT_STATUS_IS_OK(result))
761 return result;
762
763 result = rpccli_samr_OpenGroup(cli, mem_ctx,
764 &dom_pol,
765 des_access,
766 group_rid,
767 &group_pol);
768
769 if (!NT_STATUS_IS_OK(result))
770 return result;
771
772 /* Step #1: Get a list of user rids that are the members of the
773 group. */
774
775 /* This call can take a long time - allow the server to time out.
776 35 seconds should do it. */
777
778 orig_timeout = rpccli_set_timeout(cli, 35000);
779
780 result = rpccli_samr_QueryGroupMember(cli, mem_ctx,
781 &group_pol,
782 &rids);
783
784 /* And restore our original timeout. */
785 rpccli_set_timeout(cli, orig_timeout);
786
787 rpccli_samr_Close(cli, mem_ctx, &group_pol);
788
789 if (!NT_STATUS_IS_OK(result))
790 return result;
791
792 if (!rids || !rids->count) {
793 names = NULL;
794 name_types = NULL;
795 sid_mem = NULL;
796 return NT_STATUS_OK;
797 }
798
799 *num_names = rids->count;
800 rid_mem = rids->rids;
801
802 /* Step #2: Convert list of rids into list of usernames. Do this
803 in bunches of ~1000 to avoid crashing NT4. It looks like there
804 is a buffer overflow or something like that lurking around
805 somewhere. */
806
807#define MAX_LOOKUP_RIDS 900
808
809 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
810 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
811 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
812
813 for (j=0;j<(*num_names);j++)
814 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
815
816 if (*num_names>0 && (!*names || !*name_types))
817 return NT_STATUS_NO_MEMORY;
818
819 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
820 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
821 struct lsa_Strings tmp_names;
822 struct samr_Ids tmp_types;
823
824 /* Lookup a chunk of rids */
825
826 result = rpccli_samr_LookupRids(cli, mem_ctx,
827 &dom_pol,
828 num_lookup_rids,
829 &rid_mem[i],
830 &tmp_names,
831 &tmp_types);
832
833 /* see if we have a real error (and yes the
834 STATUS_SOME_UNMAPPED is the one returned from 2k) */
835
836 if (!NT_STATUS_IS_OK(result) &&
837 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
838 return result;
839
840 /* Copy result into array. The talloc system will take
841 care of freeing the temporary arrays later on. */
842
843 if (tmp_names.count != tmp_types.count) {
844 return NT_STATUS_UNSUCCESSFUL;
845 }
846
847 for (r=0; r<tmp_names.count; r++) {
848 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
849 continue;
850 }
851 (*names)[total_names] = fill_domain_username_talloc(
852 mem_ctx, domain->name,
853 tmp_names.names[r].string, true);
854 (*name_types)[total_names] = tmp_types.ids[r];
855 total_names += 1;
856 }
857 }
858
859 *num_names = total_names;
860
861 return NT_STATUS_OK;
862}
863
864#ifdef HAVE_LDAP
865
866#include <ldap.h>
867
868static int get_ldap_seq(const char *server, int port, uint32 *seq)
869{
870 int ret = -1;
871 struct timeval to;
872 const char *attrs[] = {"highestCommittedUSN", NULL};
873 LDAPMessage *res = NULL;
874 char **values = NULL;
875 LDAP *ldp = NULL;
876
877 *seq = DOM_SEQUENCE_NONE;
878
879 /*
880 * Parameterised (5) second timeout on open. This is needed as the
881 * search timeout doesn't seem to apply to doing an open as well. JRA.
882 */
883
884 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
885 if (ldp == NULL)
886 return -1;
887
888 /* Timeout if no response within 20 seconds. */
889 to.tv_sec = 10;
890 to.tv_usec = 0;
891
892 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
893 CONST_DISCARD(char **, attrs), 0, &to, &res))
894 goto done;
895
896 if (ldap_count_entries(ldp, res) != 1)
897 goto done;
898
899 values = ldap_get_values(ldp, res, "highestCommittedUSN");
900 if (!values || !values[0])
901 goto done;
902
903 *seq = atoi(values[0]);
904 ret = 0;
905
906 done:
907
908 if (values)
909 ldap_value_free(values);
910 if (res)
911 ldap_msgfree(res);
912 if (ldp)
913 ldap_unbind(ldp);
914 return ret;
915}
916
917/**********************************************************************
918 Get the sequence number for a Windows AD native mode domain using
919 LDAP queries.
920**********************************************************************/
921
922static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
923{
924 int ret = -1;
925 char addr[INET6_ADDRSTRLEN];
926
927 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
928 if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
929 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
930 "number for Domain (%s) from DC (%s)\n",
931 domain->name, addr));
932 }
933 return ret;
934}
935
936#endif /* HAVE_LDAP */
937
938/* find the sequence number for a domain */
939static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
940{
941 TALLOC_CTX *mem_ctx;
942 union samr_DomainInfo *info = NULL;
943 NTSTATUS result;
944 struct policy_handle dom_pol;
945 bool got_seq_num = False;
946 struct rpc_pipe_client *cli;
947
948 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
949
950 if ( !winbindd_can_contact_domain( domain ) ) {
951 DEBUG(10,("sequence_number: No incoming trust for domain %s\n",
952 domain->name));
953 *seq = time(NULL);
954 return NT_STATUS_OK;
955 }
956
957 *seq = DOM_SEQUENCE_NONE;
958
959 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
960 return NT_STATUS_NO_MEMORY;
961
962#ifdef HAVE_LDAP
963 if ( domain->active_directory )
964 {
965 int res;
966
967 DEBUG(8,("using get_ldap_seq() to retrieve the "
968 "sequence number\n"));
969
970 res = get_ldap_sequence_number( domain, seq );
971 if (res == 0)
972 {
973 result = NT_STATUS_OK;
974 DEBUG(10,("domain_sequence_number: LDAP for "
975 "domain %s is %u\n",
976 domain->name, *seq));
977 goto done;
978 }
979
980 DEBUG(10,("domain_sequence_number: failed to get LDAP "
981 "sequence number for domain %s\n",
982 domain->name ));
983 }
984#endif /* HAVE_LDAP */
985
986 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
987 if (!NT_STATUS_IS_OK(result)) {
988 goto done;
989 }
990
991 /* Query domain info */
992
993 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
994 &dom_pol,
995 8,
996 &info);
997
998 if (NT_STATUS_IS_OK(result)) {
999 *seq = info->info8.sequence_num;
1000 got_seq_num = True;
1001 goto seq_num;
1002 }
1003
1004 /* retry with info-level 2 in case the dc does not support info-level 8
1005 * (like all older samba2 and samba3 dc's) - Guenther */
1006
1007 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1008 &dom_pol,
1009 2,
1010 &info);
1011
1012 if (NT_STATUS_IS_OK(result)) {
1013 *seq = info->general.sequence_num;
1014 got_seq_num = True;
1015 }
1016
1017 seq_num:
1018 if (got_seq_num) {
1019 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
1020 domain->name, (unsigned)*seq));
1021 } else {
1022 DEBUG(10,("domain_sequence_number: failed to get sequence "
1023 "number (%u) for domain %s\n",
1024 (unsigned)*seq, domain->name ));
1025 }
1026
1027 done:
1028
1029 talloc_destroy(mem_ctx);
1030
1031 return result;
1032}
1033
1034/* get a list of trusted domains */
1035static NTSTATUS trusted_domains(struct winbindd_domain *domain,
1036 TALLOC_CTX *mem_ctx,
1037 struct netr_DomainTrustList *trusts)
1038{
1039 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1040 uint32 enum_ctx = 0;
1041 struct rpc_pipe_client *cli;
1042 struct policy_handle lsa_policy;
1043
1044 DEBUG(3,("rpc: trusted_domains\n"));
1045
1046 ZERO_STRUCTP(trusts);
1047
1048 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1049 if (!NT_STATUS_IS_OK(result))
1050 return result;
1051
1052 result = STATUS_MORE_ENTRIES;
1053
1054 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1055 uint32 start_idx;
1056 int i;
1057 struct lsa_DomainList dom_list;
1058
1059 result = rpccli_lsa_EnumTrustDom(cli, mem_ctx,
1060 &lsa_policy,
1061 &enum_ctx,
1062 &dom_list,
1063 (uint32_t)-1);
1064
1065 if (!NT_STATUS_IS_OK(result) &&
1066 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1067 break;
1068
1069 start_idx = trusts->count;
1070 trusts->count += dom_list.count;
1071
1072 trusts->array = talloc_realloc(
1073 mem_ctx, trusts->array, struct netr_DomainTrust,
1074 trusts->count);
1075 if (trusts->array == NULL) {
1076 return NT_STATUS_NO_MEMORY;
1077 }
1078
1079 for (i=0; i<dom_list.count; i++) {
1080 struct netr_DomainTrust *trust = &trusts->array[i];
1081 struct dom_sid *sid;
1082
1083 ZERO_STRUCTP(trust);
1084
1085 trust->netbios_name = talloc_move(
1086 trusts->array,
1087 &dom_list.domains[i].name.string);
1088 trust->dns_name = NULL;
1089
1090 sid = talloc(trusts->array, struct dom_sid);
1091 if (sid == NULL) {
1092 return NT_STATUS_NO_MEMORY;
1093 }
1094 sid_copy(sid, dom_list.domains[i].sid);
1095 trust->sid = sid;
1096 }
1097 }
1098 return result;
1099}
1100
1101/* find the lockout policy for a domain */
1102static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
1103 TALLOC_CTX *mem_ctx,
1104 struct samr_DomInfo12 *lockout_policy)
1105{
1106 NTSTATUS result;
1107 struct rpc_pipe_client *cli;
1108 struct policy_handle dom_pol;
1109 union samr_DomainInfo *info = NULL;
1110
1111 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
1112
1113 if ( !winbindd_can_contact_domain( domain ) ) {
1114 DEBUG(10,("msrpc_lockout_policy: No incoming trust for domain %s\n",
1115 domain->name));
1116 return NT_STATUS_NOT_SUPPORTED;
1117 }
1118
1119 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1120 if (!NT_STATUS_IS_OK(result)) {
1121 goto done;
1122 }
1123
1124 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1125 &dom_pol,
1126 12,
1127 &info);
1128 if (!NT_STATUS_IS_OK(result)) {
1129 goto done;
1130 }
1131
1132 *lockout_policy = info->info12;
1133
1134 DEBUG(10,("msrpc_lockout_policy: lockout_threshold %d\n",
1135 info->info12.lockout_threshold));
1136
1137 done:
1138
1139 return result;
1140}
1141
1142/* find the password policy for a domain */
1143static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
1144 TALLOC_CTX *mem_ctx,
1145 struct samr_DomInfo1 *password_policy)
1146{
1147 NTSTATUS result;
1148 struct rpc_pipe_client *cli;
1149 struct policy_handle dom_pol;
1150 union samr_DomainInfo *info = NULL;
1151
1152 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1153
1154 if ( !winbindd_can_contact_domain( domain ) ) {
1155 DEBUG(10,("msrpc_password_policy: No incoming trust for domain %s\n",
1156 domain->name));
1157 return NT_STATUS_NOT_SUPPORTED;
1158 }
1159
1160 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1161 if (!NT_STATUS_IS_OK(result)) {
1162 goto done;
1163 }
1164
1165 result = rpccli_samr_QueryDomainInfo(cli, mem_ctx,
1166 &dom_pol,
1167 1,
1168 &info);
1169 if (!NT_STATUS_IS_OK(result)) {
1170 goto done;
1171 }
1172
1173 *password_policy = info->info1;
1174
1175 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1176 info->info1.min_password_length));
1177
1178 done:
1179
1180 return result;
1181}
1182
1183typedef NTSTATUS (*lookup_sids_fn_t)(struct rpc_pipe_client *cli,
1184 TALLOC_CTX *mem_ctx,
1185 struct policy_handle *pol,
1186 int num_sids,
1187 const DOM_SID *sids,
1188 char ***pdomains,
1189 char ***pnames,
1190 enum lsa_SidType **ptypes);
1191
1192NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
1193 struct winbindd_domain *domain,
1194 uint32_t num_sids,
1195 const struct dom_sid *sids,
1196 char ***domains,
1197 char ***names,
1198 enum lsa_SidType **types)
1199{
1200 NTSTATUS status;
1201 struct rpc_pipe_client *cli = NULL;
1202 struct policy_handle lsa_policy;
1203 unsigned int orig_timeout;
1204 lookup_sids_fn_t lookup_sids_fn = rpccli_lsa_lookup_sids;
1205
1206 if (domain->can_do_ncacn_ip_tcp) {
1207 status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
1208 if (NT_STATUS_IS_OK(status)) {
1209 lookup_sids_fn = rpccli_lsa_lookup_sids3;
1210 goto lookup;
1211 }
1212 domain->can_do_ncacn_ip_tcp = false;
1213 }
1214 status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1215
1216 if (!NT_STATUS_IS_OK(status)) {
1217 return status;
1218 }
1219
1220 lookup:
1221 /*
1222 * This call can take a long time
1223 * allow the server to time out.
1224 * 35 seconds should do it.
1225 */
1226 orig_timeout = rpccli_set_timeout(cli, 35000);
1227
1228 status = lookup_sids_fn(cli,
1229 mem_ctx,
1230 &lsa_policy,
1231 num_sids,
1232 sids,
1233 domains,
1234 names,
1235 types);
1236
1237 /* And restore our original timeout. */
1238 rpccli_set_timeout(cli, orig_timeout);
1239
1240 if (NT_STATUS_V(status) == DCERPC_FAULT_ACCESS_DENIED ||
1241 NT_STATUS_V(status) == DCERPC_FAULT_SEC_PKG_ERROR) {
1242 /*
1243 * This can happen if the schannel key is not
1244 * valid anymore, we need to invalidate the
1245 * all connections to the dc and reestablish
1246 * a netlogon connection first.
1247 */
1248 invalidate_cm_connection(&domain->conn);
1249 status = NT_STATUS_ACCESS_DENIED;
1250 }
1251
1252 if (!NT_STATUS_IS_OK(status)) {
1253 return status;
1254 }
1255
1256 return status;
1257}
1258
1259typedef NTSTATUS (*lookup_names_fn_t)(struct rpc_pipe_client *cli,
1260 TALLOC_CTX *mem_ctx,
1261 struct policy_handle *pol,
1262 int num_names,
1263 const char **names,
1264 const char ***dom_names,
1265 int level,
1266 struct dom_sid **sids,
1267 enum lsa_SidType **types);
1268
1269NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
1270 struct winbindd_domain *domain,
1271 uint32_t num_names,
1272 const char **names,
1273 const char ***domains,
1274 struct dom_sid **sids,
1275 enum lsa_SidType **types)
1276{
1277 NTSTATUS status;
1278 struct rpc_pipe_client *cli = NULL;
1279 struct policy_handle lsa_policy;
1280 unsigned int orig_timeout = 0;
1281 lookup_names_fn_t lookup_names_fn = rpccli_lsa_lookup_names;
1282
1283 if (domain->can_do_ncacn_ip_tcp) {
1284 status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
1285 if (NT_STATUS_IS_OK(status)) {
1286 lookup_names_fn = rpccli_lsa_lookup_names4;
1287 goto lookup;
1288 }
1289 domain->can_do_ncacn_ip_tcp = false;
1290 }
1291 status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
1292
1293 if (!NT_STATUS_IS_OK(status)) {
1294 return status;
1295 }
1296
1297 lookup:
1298
1299 /*
1300 * This call can take a long time
1301 * allow the server to time out.
1302 * 35 seconds should do it.
1303 */
1304 orig_timeout = rpccli_set_timeout(cli, 35000);
1305
1306 status = lookup_names_fn(cli,
1307 mem_ctx,
1308 &lsa_policy,
1309 num_names,
1310 (const char **) names,
1311 domains,
1312 1,
1313 sids,
1314 types);
1315
1316 /* And restore our original timeout. */
1317 rpccli_set_timeout(cli, orig_timeout);
1318
1319 if (NT_STATUS_V(status) == DCERPC_FAULT_ACCESS_DENIED ||
1320 NT_STATUS_V(status) == DCERPC_FAULT_SEC_PKG_ERROR) {
1321 /*
1322 * This can happen if the schannel key is not
1323 * valid anymore, we need to invalidate the
1324 * all connections to the dc and reestablish
1325 * a netlogon connection first.
1326 */
1327 invalidate_cm_connection(&domain->conn);
1328 status = NT_STATUS_ACCESS_DENIED;
1329 }
1330
1331 if (!NT_STATUS_IS_OK(status)) {
1332 return status;
1333 }
1334
1335 return status;
1336}
1337
1338/* the rpc backend methods are exposed via this structure */
1339struct winbindd_methods msrpc_methods = {
1340 False,
1341 query_user_list,
1342 enum_dom_groups,
1343 enum_local_groups,
1344 msrpc_name_to_sid,
1345 msrpc_sid_to_name,
1346 msrpc_rids_to_names,
1347 query_user,
1348 lookup_usergroups,
1349 msrpc_lookup_useraliases,
1350 lookup_groupmem,
1351 sequence_number,
1352 msrpc_lockout_policy,
1353 msrpc_password_policy,
1354 trusted_domains,
1355};
Note: See TracBrowser for help on using the repository browser.