source: branches/samba-3.3.x/source/winbindd/winbindd_rpc.c@ 342

Last change on this file since 342 was 342, checked in by Herwig Bauernfeind, 15 years ago

Update 3.3 to 3.3.9

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