~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/nsswitch/winbindd_rpc.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

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