source: branches/samba-3.0/source/nsswitch/winbindd_rpc.c

Last change on this file was 165, checked in by Paul Smedley, 16 years ago

Add 'missing' 3.0.34 diffs

File size: 25.8 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
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 2 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, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
52 if (!NT_STATUS_IS_OK(result))
53 return result;
54
55 i = start_idx = 0;
56 loop_count = 0;
57
58 do {
59 TALLOC_CTX *ctx2;
60 uint32 num_dom_users, j;
61 uint32 max_entries, max_size;
62 SAM_DISPINFO_CTR ctr;
63 SAM_DISPINFO_1 info1;
64
65 ZERO_STRUCT( ctr );
66 ZERO_STRUCT( info1 );
67 ctr.sam.info1 = &info1;
68
69 if (!(ctx2 = talloc_init("winbindd enum_users")))
70 return NT_STATUS_NO_MEMORY;
71
72 /* this next bit is copied from net_user_list_internal() */
73
74 get_query_dispinfo_params(loop_count, &max_entries,
75 &max_size);
76
77 result = rpccli_samr_query_dispinfo(cli, mem_ctx, &dom_pol,
78 &start_idx, 1,
79 &num_dom_users,
80 max_entries, max_size,
81 &ctr);
82
83 loop_count++;
84
85 *num_entries += num_dom_users;
86
87 *info = TALLOC_REALLOC_ARRAY(mem_ctx, *info, WINBIND_USERINFO,
88 *num_entries);
89
90 if (!(*info)) {
91 talloc_destroy(ctx2);
92 return NT_STATUS_NO_MEMORY;
93 }
94
95 for (j = 0; j < num_dom_users; i++, j++) {
96 fstring username, fullname;
97 uint32 rid = ctr.sam.info1->sam[j].rid_user;
98
99 unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)-1);
100 unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)-1);
101
102 (*info)[i].acct_name = talloc_strdup(mem_ctx, username );
103 (*info)[i].full_name = talloc_strdup(mem_ctx, fullname );
104 (*info)[i].homedir = NULL;
105 (*info)[i].shell = NULL;
106 sid_compose(&(*info)[i].user_sid, &domain->sid, rid);
107
108 /* For the moment we set the primary group for
109 every user to be the Domain Users group.
110 There are serious problems with determining
111 the actual primary group for large domains.
112 This should really be made into a 'winbind
113 force group' smb.conf parameter or
114 something like that. */
115
116 sid_compose(&(*info)[i].group_sid, &domain->sid,
117 DOMAIN_GROUP_RID_USERS);
118 }
119
120 talloc_destroy(ctx2);
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 status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
144 if (!NT_STATUS_IS_OK(status))
145 return status;
146
147 do {
148 struct acct_info *info2 = NULL;
149 uint32 count = 0;
150 TALLOC_CTX *mem_ctx2;
151
152 mem_ctx2 = talloc_init("enum_dom_groups[rpc]");
153
154 /* start is updated by this call. */
155 status = rpccli_samr_enum_dom_groups(cli, mem_ctx2, &dom_pol,
156 &start,
157 0xFFFF, /* buffer size? */
158 &info2, &count);
159
160 if (!NT_STATUS_IS_OK(status) &&
161 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
162 talloc_destroy(mem_ctx2);
163 break;
164 }
165
166 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
167 struct acct_info,
168 (*num_entries) + count);
169 if (! *info) {
170 talloc_destroy(mem_ctx2);
171 return NT_STATUS_NO_MEMORY;
172 }
173
174 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
175 (*num_entries) += count;
176 talloc_destroy(mem_ctx2);
177 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
178
179 return NT_STATUS_OK;
180}
181
182/* List all domain groups */
183
184static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
185 TALLOC_CTX *mem_ctx,
186 uint32 *num_entries,
187 struct acct_info **info)
188{
189 POLICY_HND dom_pol;
190 NTSTATUS result;
191 struct rpc_pipe_client *cli;
192
193 *num_entries = 0;
194 *info = NULL;
195
196 DEBUG(3,("rpc: enum_local_groups\n"));
197
198 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
199 if (!NT_STATUS_IS_OK(result))
200 return result;
201
202 do {
203 struct acct_info *info2 = NULL;
204 uint32 count = 0, start = *num_entries;
205 TALLOC_CTX *mem_ctx2;
206
207 mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]");
208
209 result = rpccli_samr_enum_als_groups( cli, mem_ctx2, &dom_pol,
210 &start, 0xFFFF, &info2,
211 &count);
212
213 if (!NT_STATUS_IS_OK(result) &&
214 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) )
215 {
216 talloc_destroy(mem_ctx2);
217 return result;
218 }
219
220 (*info) = TALLOC_REALLOC_ARRAY(mem_ctx, *info,
221 struct acct_info,
222 (*num_entries) + count);
223 if (! *info) {
224 talloc_destroy(mem_ctx2);
225 return NT_STATUS_NO_MEMORY;
226 }
227
228 memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2));
229 (*num_entries) += count;
230 talloc_destroy(mem_ctx2);
231
232 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
233
234 return NT_STATUS_OK;
235}
236
237/* convert a single name to a sid in a domain */
238static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
239 TALLOC_CTX *mem_ctx,
240 const char *domain_name,
241 const char *name,
242 DOM_SID *sid,
243 enum lsa_SidType *type)
244{
245 NTSTATUS result;
246 DOM_SID *sids = NULL;
247 enum lsa_SidType *types = NULL;
248 char *full_name = NULL;
249 struct rpc_pipe_client *cli;
250 POLICY_HND lsa_policy;
251
252 if(name == NULL || *name=='\0') {
253 DEBUG(3,("rpc: name_to_sid name=%s\n", domain_name));
254 full_name = talloc_asprintf(mem_ctx, "%s", domain_name);
255 } else {
256 DEBUG(3,("rpc: name_to_sid name=%s\\%s\n", domain_name, name));
257 full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain_name, name);
258 }
259 if (!full_name) {
260 DEBUG(0, ("talloc_asprintf failed!\n"));
261 return NT_STATUS_NO_MEMORY;
262 }
263
264 ws_name_return( full_name, WB_REPLACE_CHAR );
265
266 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
267
268 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
269 if (!NT_STATUS_IS_OK(result))
270 return result;
271
272 result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1,
273 (const char**) &full_name, NULL, &sids, &types);
274
275 if (!NT_STATUS_IS_OK(result))
276 return result;
277
278 /* Return rid and type if lookup successful */
279
280 sid_copy(sid, &sids[0]);
281 *type = types[0];
282
283 return NT_STATUS_OK;
284}
285
286/*
287 convert a domain SID to a user or group name
288*/
289static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
290 TALLOC_CTX *mem_ctx,
291 const DOM_SID *sid,
292 char **domain_name,
293 char **name,
294 enum lsa_SidType *type)
295{
296 char **domains;
297 char **names;
298 enum lsa_SidType *types;
299 NTSTATUS result;
300 struct rpc_pipe_client *cli;
301 POLICY_HND lsa_policy;
302
303 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
304 domain->name ));
305
306 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
307 if (!NT_STATUS_IS_OK(result))
308 return result;
309
310 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
311 1, sid, &domains, &names, &types);
312 if (!NT_STATUS_IS_OK(result))
313 return result;
314
315 *type = (enum lsa_SidType)types[0];
316 *domain_name = domains[0];
317 *name = names[0];
318
319 ws_name_replace( *name, WB_REPLACE_CHAR );
320
321 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
322 return NT_STATUS_OK;
323}
324
325static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
326 TALLOC_CTX *mem_ctx,
327 const DOM_SID *sid,
328 uint32 *rids,
329 size_t num_rids,
330 char **domain_name,
331 char ***names,
332 enum lsa_SidType **types)
333{
334 char **domains;
335 NTSTATUS result;
336 struct rpc_pipe_client *cli;
337 POLICY_HND lsa_policy;
338 DOM_SID *sids;
339 size_t i;
340 char **ret_names;
341
342 DEBUG(3, ("rids_to_names [rpc] for domain %s\n", domain->name ));
343
344 if (num_rids) {
345 sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_rids);
346 if (sids == NULL) {
347 return NT_STATUS_NO_MEMORY;
348 }
349 } else {
350 sids = NULL;
351 }
352
353 for (i=0; i<num_rids; i++) {
354 if (!sid_compose(&sids[i], sid, rids[i])) {
355 return NT_STATUS_INTERNAL_ERROR;
356 }
357 }
358
359 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
360 if (!NT_STATUS_IS_OK(result)) {
361 return result;
362 }
363
364 result = rpccli_lsa_lookup_sids(cli, mem_ctx, &lsa_policy,
365 num_rids, sids, &domains,
366 names, types);
367 if (!NT_STATUS_IS_OK(result) &&
368 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
369 return result;
370 }
371
372 ret_names = *names;
373 for (i=0; i<num_rids; i++) {
374 if ((*types)[i] != SID_NAME_UNKNOWN) {
375 ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
376 *domain_name = domains[i];
377 }
378 }
379
380 return result;
381}
382
383/* Lookup user information from a rid or username. */
384static NTSTATUS query_user(struct winbindd_domain *domain,
385 TALLOC_CTX *mem_ctx,
386 const DOM_SID *user_sid,
387 WINBIND_USERINFO *user_info)
388{
389 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
390 POLICY_HND dom_pol, user_pol;
391 SAM_USERINFO_CTR *ctr;
392 fstring sid_string;
393 uint32 user_rid;
394 NET_USER_INFO_3 *user;
395 struct rpc_pipe_client *cli;
396
397 DEBUG(3,("rpc: query_user sid=%s\n",
398 sid_to_string(sid_string, user_sid)));
399
400 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
401 return NT_STATUS_UNSUCCESSFUL;
402
403 /* try netsamlogon cache first */
404
405 if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
406 {
407
408 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
409 sid_string_static(user_sid)));
410
411 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
412 sid_compose(&user_info->group_sid, &domain->sid,
413 user->group_rid);
414
415 user_info->acct_name = unistr2_tdup(mem_ctx,
416 &user->uni_user_name);
417 user_info->full_name = unistr2_tdup(mem_ctx,
418 &user->uni_full_name);
419
420 user_info->homedir = NULL;
421 user_info->shell = NULL;
422 user_info->primary_gid = (gid_t)-1;
423
424 TALLOC_FREE(user);
425
426 return NT_STATUS_OK;
427 }
428
429 /* no cache; hit the wire */
430
431 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
432 if (!NT_STATUS_IS_OK(result))
433 return result;
434
435 /* Get user handle */
436 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
437 SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
438 &user_pol);
439
440 if (!NT_STATUS_IS_OK(result))
441 return result;
442
443 /* Get user info */
444 result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
445 0x15, &ctr);
446
447 rpccli_samr_close(cli, mem_ctx, &user_pol);
448
449 if (!NT_STATUS_IS_OK(result))
450 return result;
451
452 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
453 sid_compose(&user_info->group_sid, &domain->sid,
454 ctr->info.id21->group_rid);
455 user_info->acct_name = unistr2_tdup(mem_ctx,
456 &ctr->info.id21->uni_user_name);
457 user_info->full_name = unistr2_tdup(mem_ctx,
458 &ctr->info.id21->uni_full_name);
459 user_info->homedir = NULL;
460 user_info->shell = NULL;
461 user_info->primary_gid = (gid_t)-1;
462
463 return NT_STATUS_OK;
464}
465
466/* Lookup groups a user is a member of. I wish Unix had a call like this! */
467static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
468 TALLOC_CTX *mem_ctx,
469 const DOM_SID *user_sid,
470 uint32 *num_groups, DOM_SID **user_grpsids)
471{
472 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
473 POLICY_HND dom_pol, user_pol;
474 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
475 DOM_GID *user_groups;
476 unsigned int i;
477 fstring sid_string;
478 uint32 user_rid;
479 struct rpc_pipe_client *cli;
480
481 DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
482 sid_to_string(sid_string, user_sid)));
483
484 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid))
485 return NT_STATUS_UNSUCCESSFUL;
486
487 *num_groups = 0;
488 *user_grpsids = NULL;
489
490 /* so lets see if we have a cached user_info_3 */
491 result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
492 num_groups, user_grpsids);
493
494 if (NT_STATUS_IS_OK(result)) {
495 return NT_STATUS_OK;
496 }
497
498 /* no cache; hit the wire */
499
500 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
501 if (!NT_STATUS_IS_OK(result))
502 return result;
503
504 /* Get user handle */
505 result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
506 des_access, user_rid, &user_pol);
507
508 if (!NT_STATUS_IS_OK(result))
509 return result;
510
511 /* Query user rids */
512 result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
513 num_groups, &user_groups);
514
515 rpccli_samr_close(cli, mem_ctx, &user_pol);
516
517 if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
518 return result;
519
520 (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
521 if (!(*user_grpsids))
522 return NT_STATUS_NO_MEMORY;
523
524 for (i=0;i<(*num_groups);i++) {
525 sid_copy(&((*user_grpsids)[i]), &domain->sid);
526 sid_append_rid(&((*user_grpsids)[i]),
527 user_groups[i].g_rid);
528 }
529
530 return NT_STATUS_OK;
531}
532
533static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
534 TALLOC_CTX *mem_ctx,
535 uint32 num_sids, const DOM_SID *sids,
536 uint32 *num_aliases,
537 uint32 **alias_rids)
538{
539 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
540 POLICY_HND dom_pol;
541 DOM_SID2 *query_sids;
542 uint32 num_query_sids = 0;
543 int i;
544 struct rpc_pipe_client *cli;
545 uint32 *alias_rids_query, num_aliases_query;
546 int rangesize = MAX_SAM_ENTRIES_W2K;
547 uint32 total_sids = 0;
548 int num_queries = 1;
549
550 *num_aliases = 0;
551 *alias_rids = NULL;
552
553 DEBUG(3,("rpc: lookup_useraliases\n"));
554
555 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
556 if (!NT_STATUS_IS_OK(result))
557 return result;
558
559 do {
560 /* prepare query */
561
562 num_query_sids = MIN(num_sids - total_sids, rangesize);
563
564 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
565 num_queries, num_query_sids));
566
567 if (num_query_sids) {
568 query_sids = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_query_sids);
569 if (query_sids == NULL) {
570 return NT_STATUS_NO_MEMORY;
571 }
572 } else {
573 query_sids = NULL;
574 }
575
576 for (i=0; i<num_query_sids; i++) {
577 sid_copy(&query_sids[i].sid, &sids[total_sids++]);
578 query_sids[i].num_auths = query_sids[i].sid.num_auths;
579 }
580
581 /* do request */
582
583 result = rpccli_samr_query_useraliases(cli, mem_ctx, &dom_pol,
584 num_query_sids, query_sids,
585 &num_aliases_query,
586 &alias_rids_query);
587
588 if (!NT_STATUS_IS_OK(result)) {
589 *num_aliases = 0;
590 *alias_rids = NULL;
591 TALLOC_FREE(query_sids);
592 goto done;
593 }
594
595 /* process output */
596
597 for (i=0; i<num_aliases_query; i++) {
598 size_t na = *num_aliases;
599 if (!add_rid_to_array_unique(mem_ctx, alias_rids_query[i],
600 alias_rids, &na)) {
601 return NT_STATUS_NO_MEMORY;
602 }
603 *num_aliases = na;
604 }
605
606 TALLOC_FREE(query_sids);
607
608 num_queries++;
609
610 } while (total_sids < num_sids);
611
612 done:
613 DEBUG(10,("rpc: lookup_useraliases: got %d aliases in %d queries "
614 "(rangesize: %d)\n", *num_aliases, num_queries, rangesize));
615
616 return result;
617}
618
619
620/* Lookup group membership given a rid. */
621static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
622 TALLOC_CTX *mem_ctx,
623 const DOM_SID *group_sid, uint32 *num_names,
624 DOM_SID **sid_mem, char ***names,
625 uint32 **name_types)
626{
627 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
628 uint32 i, total_names = 0;
629 POLICY_HND dom_pol, group_pol;
630 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
631 uint32 *rid_mem = NULL;
632 uint32 group_rid;
633 unsigned int j;
634 fstring sid_string;
635 struct rpc_pipe_client *cli;
636 unsigned int orig_timeout;
637
638 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name,
639 sid_to_string(sid_string, group_sid)));
640
641 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid))
642 return NT_STATUS_UNSUCCESSFUL;
643
644 *num_names = 0;
645
646 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
647 if (!NT_STATUS_IS_OK(result))
648 return result;
649
650 result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
651 des_access, group_rid, &group_pol);
652
653 if (!NT_STATUS_IS_OK(result))
654 return result;
655
656 /* Step #1: Get a list of user rids that are the members of the
657 group. */
658
659 /* This call can take a long time - allow the server to time out.
660 35 seconds should do it. */
661
662 orig_timeout = cli_set_timeout(cli->cli, 35000);
663
664 result = rpccli_samr_query_groupmem(cli, mem_ctx,
665 &group_pol, num_names, &rid_mem,
666 name_types);
667
668 /* And restore our original timeout. */
669 cli_set_timeout(cli->cli, orig_timeout);
670
671 rpccli_samr_close(cli, mem_ctx, &group_pol);
672
673 if (!NT_STATUS_IS_OK(result))
674 return result;
675
676 if (!*num_names) {
677 names = NULL;
678 name_types = NULL;
679 sid_mem = NULL;
680 return NT_STATUS_OK;
681 }
682
683 /* Step #2: Convert list of rids into list of usernames. Do this
684 in bunches of ~1000 to avoid crashing NT4. It looks like there
685 is a buffer overflow or something like that lurking around
686 somewhere. */
687
688#define MAX_LOOKUP_RIDS 900
689
690 *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
691 *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
692 *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_names);
693
694 for (j=0;j<(*num_names);j++)
695 sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
696
697 if (*num_names>0 && (!*names || !*name_types))
698 return NT_STATUS_NO_MEMORY;
699
700 for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) {
701 int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS);
702 uint32 tmp_num_names = 0;
703 char **tmp_names = NULL;
704 uint32 *tmp_types = NULL;
705
706 /* Lookup a chunk of rids */
707
708 result = rpccli_samr_lookup_rids(cli, mem_ctx,
709 &dom_pol,
710 num_lookup_rids,
711 &rid_mem[i],
712 &tmp_num_names,
713 &tmp_names, &tmp_types);
714
715 /* see if we have a real error (and yes the
716 STATUS_SOME_UNMAPPED is the one returned from 2k) */
717
718 if (!NT_STATUS_IS_OK(result) &&
719 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
720 return result;
721
722 /* Copy result into array. The talloc system will take
723 care of freeing the temporary arrays later on. */
724
725 memcpy(&(*names)[i], tmp_names, sizeof(char *) *
726 tmp_num_names);
727
728 memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) *
729 tmp_num_names);
730
731 total_names += tmp_num_names;
732 }
733
734 *num_names = total_names;
735
736 return NT_STATUS_OK;
737}
738
739#ifdef HAVE_LDAP
740
741#include <ldap.h>
742
743static int get_ldap_seq(const char *server, int port, uint32 *seq)
744{
745 int ret = -1;
746 struct timeval to;
747 const char *attrs[] = {"highestCommittedUSN", NULL};
748 LDAPMessage *res = NULL;
749 char **values = NULL;
750 LDAP *ldp = NULL;
751
752 *seq = DOM_SEQUENCE_NONE;
753
754 /*
755 * Parameterised (5) second timeout on open. This is needed as the
756 * search timeout doesn't seem to apply to doing an open as well. JRA.
757 */
758
759 ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
760 if (ldp == NULL)
761 return -1;
762
763 /* Timeout if no response within 20 seconds. */
764 to.tv_sec = 10;
765 to.tv_usec = 0;
766
767 if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
768 CONST_DISCARD(char **, attrs), 0, &to, &res))
769 goto done;
770
771 if (ldap_count_entries(ldp, res) != 1)
772 goto done;
773
774 values = ldap_get_values(ldp, res, "highestCommittedUSN");
775 if (!values || !values[0])
776 goto done;
777
778 *seq = atoi(values[0]);
779 ret = 0;
780
781 done:
782
783 if (values)
784 ldap_value_free(values);
785 if (res)
786 ldap_msgfree(res);
787 if (ldp)
788 ldap_unbind(ldp);
789 return ret;
790}
791
792/**********************************************************************
793 Get the sequence number for a Windows AD native mode domain using
794 LDAP queries.
795**********************************************************************/
796
797static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
798{
799 int ret = -1;
800 fstring ipstr;
801
802 fstrcpy( ipstr, inet_ntoa(domain->dcaddr.sin_addr));
803 if ((ret = get_ldap_seq( ipstr, LDAP_PORT, seq)) == 0) {
804 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
805 "number for Domain (%s) from DC (%s)\n",
806 domain->name, ipstr));
807 }
808 return ret;
809}
810
811#endif /* HAVE_LDAP */
812
813/* find the sequence number for a domain */
814static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
815{
816 TALLOC_CTX *mem_ctx;
817 SAM_UNK_CTR ctr;
818 NTSTATUS result;
819 POLICY_HND dom_pol;
820 BOOL got_seq_num = False;
821 struct rpc_pipe_client *cli;
822
823 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
824
825 *seq = DOM_SEQUENCE_NONE;
826
827 if (!(mem_ctx = talloc_init("sequence_number[rpc]")))
828 return NT_STATUS_NO_MEMORY;
829
830#ifdef HAVE_LDAP
831 if ( domain->native_mode )
832 {
833 int res;
834
835 DEBUG(8,("using get_ldap_seq() to retrieve the "
836 "sequence number\n"));
837
838 res = get_ldap_sequence_number( domain, seq );
839 if (res == 0)
840 {
841 result = NT_STATUS_OK;
842 DEBUG(10,("domain_sequence_number: LDAP for "
843 "domain %s is %u\n",
844 domain->name, *seq));
845 goto done;
846 }
847
848 DEBUG(10,("domain_sequence_number: failed to get LDAP "
849 "sequence number for domain %s\n",
850 domain->name ));
851 }
852#endif /* HAVE_LDAP */
853
854 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
855 if (!NT_STATUS_IS_OK(result)) {
856 goto done;
857 }
858
859 /* Query domain info */
860
861 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 8, &ctr);
862
863 if (NT_STATUS_IS_OK(result)) {
864 *seq = ctr.info.inf8.seq_num;
865 got_seq_num = True;
866 goto seq_num;
867 }
868
869 /* retry with info-level 2 in case the dc does not support info-level 8
870 * (like all older samba2 and samba3 dc's - Guenther */
871
872 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 2, &ctr);
873
874 if (NT_STATUS_IS_OK(result)) {
875 *seq = ctr.info.inf2.seq_num;
876 got_seq_num = True;
877 }
878
879 seq_num:
880 if (got_seq_num) {
881 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
882 domain->name, (unsigned)*seq));
883 } else {
884 DEBUG(10,("domain_sequence_number: failed to get sequence "
885 "number (%u) for domain %s\n",
886 (unsigned)*seq, domain->name ));
887 }
888
889 done:
890
891 talloc_destroy(mem_ctx);
892
893 return result;
894}
895
896/* get a list of trusted domains */
897static NTSTATUS trusted_domains(struct winbindd_domain *domain,
898 TALLOC_CTX *mem_ctx,
899 uint32 *num_domains,
900 char ***names,
901 char ***alt_names,
902 DOM_SID **dom_sids)
903{
904 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
905 uint32 enum_ctx = 0;
906 struct rpc_pipe_client *cli;
907 POLICY_HND lsa_policy;
908
909 DEBUG(3,("rpc: trusted_domains\n"));
910
911 *num_domains = 0;
912 *names = NULL;
913 *alt_names = NULL;
914 *dom_sids = NULL;
915
916 result = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
917 if (!NT_STATUS_IS_OK(result))
918 return result;
919
920 result = STATUS_MORE_ENTRIES;
921
922 while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
923 uint32 start_idx, num;
924 char **tmp_names;
925 DOM_SID *tmp_sids;
926 int i;
927
928 result = rpccli_lsa_enum_trust_dom(cli, mem_ctx,
929 &lsa_policy, &enum_ctx,
930 &num, &tmp_names,
931 &tmp_sids);
932
933 if (!NT_STATUS_IS_OK(result) &&
934 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
935 break;
936
937 start_idx = *num_domains;
938 *num_domains += num;
939 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
940 char *, *num_domains);
941 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
942 DOM_SID, *num_domains);
943 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names,
944 char *, *num_domains);
945 if ((*names == NULL) || (*dom_sids == NULL) ||
946 (*alt_names == NULL))
947 return NT_STATUS_NO_MEMORY;
948
949 for (i=0; i<num; i++) {
950 (*names)[start_idx+i] = tmp_names[i];
951 (*dom_sids)[start_idx+i] = tmp_sids[i];
952 (*alt_names)[start_idx+i] = talloc_strdup(mem_ctx, "");
953 }
954 }
955 return result;
956}
957
958/* find the lockout policy for a domain */
959static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
960 TALLOC_CTX *mem_ctx,
961 SAM_UNK_INFO_12 *lockout_policy)
962{
963 NTSTATUS result;
964 struct rpc_pipe_client *cli;
965 POLICY_HND dom_pol;
966 SAM_UNK_CTR ctr;
967
968 DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
969
970 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
971 if (!NT_STATUS_IS_OK(result)) {
972 goto done;
973 }
974
975 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
976 if (!NT_STATUS_IS_OK(result)) {
977 goto done;
978 }
979
980 *lockout_policy = ctr.info.inf12;
981
982 DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n",
983 ctr.info.inf12.bad_attempt_lockout));
984
985 done:
986
987 return result;
988}
989
990/* find the password policy for a domain */
991static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
992 TALLOC_CTX *mem_ctx,
993 SAM_UNK_INFO_1 *password_policy)
994{
995 NTSTATUS result;
996 struct rpc_pipe_client *cli;
997 POLICY_HND dom_pol;
998 SAM_UNK_CTR ctr;
999
1000 DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
1001
1002 result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
1003 if (!NT_STATUS_IS_OK(result)) {
1004 goto done;
1005 }
1006
1007 result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
1008 if (!NT_STATUS_IS_OK(result)) {
1009 goto done;
1010 }
1011
1012 *password_policy = ctr.info.inf1;
1013
1014 DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
1015 ctr.info.inf1.min_length_password));
1016
1017 done:
1018
1019 return result;
1020}
1021
1022
1023/* the rpc backend methods are exposed via this structure */
1024struct winbindd_methods msrpc_methods = {
1025 False,
1026 query_user_list,
1027 enum_dom_groups,
1028 enum_local_groups,
1029 msrpc_name_to_sid,
1030 msrpc_sid_to_name,
1031 msrpc_rids_to_names,
1032 query_user,
1033 lookup_usergroups,
1034 msrpc_lookup_useraliases,
1035 lookup_groupmem,
1036 sequence_number,
1037 msrpc_lockout_policy,
1038 msrpc_password_policy,
1039 trusted_domains,
1040};
Note: See TracBrowser for help on using the repository browser.